home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / prgemtex.lzh / TEX / PROFGEM.TEX < prev   
Encoding:
Text File  |  1991-09-15  |  324.6 KB  |  6,618 lines

  1. % SUBJECT: Professional GEM, 09.09.91
  2. %
  3. % These are all the sections. Appendix A-C are include files
  4. % (app_a.tex, app_b.tex, app_c.tex).
  5. %
  6. % Layout changes:
  7. %
  8. % all sans-serif emphasizes removed 09.09.1991 - mo
  9.  
  10. % 4 Ollie's DIN-5 zoom...
  11. % \documentstyle[12pt,a4,twoside,titlepage]{article}
  12. %
  13.  
  14. \documentstyle[a4wide,twoside,titlepage]{article}
  15.  
  16. \pagestyle{headings}
  17.  
  18. %\textwidth15.6cm\textheight23cm
  19.  
  20. \sloppy
  21.  
  22. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  23. \begin{document}
  24.  
  25. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  26.  
  27. \title{Professional GEM}
  28. \author{by Tim Oren}
  29.  
  30. \maketitle
  31. \newpage
  32.  
  33. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  34. \pagenumbering{roman}
  35. \tableofcontents\clearpage
  36. \newpage
  37. \pagenumbering{arabic}
  38.  
  39. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  40. \section{Introduction}
  41.  
  42. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  43. \subsection{Hello, world!}
  44.  
  45.    For those whom I have not met in person or  electronically, an
  46. introduction is in order.
  47.  
  48.    I am a former member of the GEM programming team at Digital Research,
  49. Inc., where I designed and implemented the GEM Resource Construction
  50. Set and other parts of the GEM Programmer's Toolkit.  I have since
  51. left DRI to become the user interface designer for Activenture, a
  52. startup company which is developing CD-ROM technology for use with
  53. the Atari ST and other systems.
  54.  
  55.    The purpose of Professional GEM is to pass along  some of the
  56. information and tricks I have accumulated about GEM, and explore some
  57. of the user interface techniques which a powerful graphics processor
  58. such as the ST makes possible.
  59.  
  60. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  61. \subsection{Ground Rules}
  62.  
  63.    I am going to assume that you have both a working  knowledge of the C
  64. programming language and a copy of the ST Programmer's Toolkit with
  65. documentation (available from Atari).  If you lack either, don't
  66. panic.  You can read the columns to get the flavor of programming the
  67. ST, and come back for a more serious visit later on.
  68.  
  69.    For now, I will be using code samples that will run with the
  70. Atari-supplied C compiler, also known as DR C-68K, or Alcyon C.  I
  71. will be using the portability macros supplied with the Toolkit, so
  72. that the code will also be transferable to other GEM systems.
  73.  
  74.    Both of these items are subject to change, depending on  reader
  75. feedback and the availability of better products.
  76.  
  77.    If you do not have a copy of the source to the {\tt DOODLE.C} GEM example
  78. program, you should  consider downloading a copy from SIG*ATARI.
  79. Although it is poorly documented, it shows real-life examples of many
  80. of the techniques I will  discuss.
  81.  
  82.    Getting started with a windowed graphics system seems to be like
  83. getting into an ice-cold swimming pool: it's best done all at once.
  84.  
  85.    Anyone who has looked at {\em Inside Macintosh} has probably noticed that
  86. you have to have read most of it to understand any of it.  GEM isn't
  87. really much  different.  You have all the reference guides in your
  88. hand, but nothing to show how it all works together.
  89.  
  90.    I am hoping to help this situation by leading a series of short tours
  91. through the GEM jungle.  Each time we'll go out with a particular
  92. goal in mind and follow the path that leads there.  We'll look at the
  93. pitfalls and strange bugs that lurk for the unwary, and show off a
  94. few tricks to  amaze the natives.  The first trip leaves immediately;
  95. our mission is to get a window onto the ST screen, with all of its
  96. parts properly initialized.
  97. \newpage
  98.  
  99. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  100. \section{Windows}
  101.  
  102. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  103. \subsection{We do windows}
  104.  
  105.    One of the most important services which a graphics interface system
  106. provides for the user and programmer is window management.
  107.  
  108.    Windows allow the user to perform more than one activity on the same
  109. screen, to freely reallocate areas of the screen for each task, and
  110. even to pile the information up like pages of paper to make more
  111. room.  The price for this increased freedom is (as usual) paid by
  112. you, the programmer, who must master a more complex method of
  113. interacting with the ``outside world''.
  114.  
  115.    The windowing routines provided by ST GEM are the most comprehensive
  116. yet available in a low-cost microcomputer.  This article is a guide
  117. to using these services in an effective manner.
  118.  
  119. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  120. \subsection{In the beginning}
  121.  
  122.    In GEM, creating a window and displaying it are two different
  123. functions.  The creation function is called {\tt wind\_create}, and its
  124. calling sequence is:
  125.  
  126. \begin{verbatim}
  127.    handle = wind_create(parts, xfull, yfull, wfull, hfull);
  128. \end{verbatim}
  129.  
  130.    This function asks GEM to reserve space in its memory for a new
  131. window  description, and to return a code or {\em handle}\/ which you can
  132. use to refer to the window in the future.  Valid window handles are
  133. positive integers; they are not memory pointers.
  134.  
  135.    GEM can run out of window handles.  If it does so, the value returned
  136. is negative.  Your code should always check for this  situation and
  137. ask the program's user to close some windows and retry if  possible.
  138. Handle zero is special.  It refers to the {\em desktop}, which is
  139. predefined as light green (or gray) on the ST.  Window zero is always
  140. present and may be used, but never deleted, by the programmer.
  141.  
  142.    The  {\tt xfull}, {\tt yfull}, {\tt wfull}, and {\tt hfull}\/ parameters
  143. are integers which determine the maximum size of the window.
  144. {\tt xfull}\/ and {\tt yfull}\/ define the upper left corner of the window,
  145. and {\tt wfull}\/ and {\tt hfull}\/ specify its width and height.
  146. (Note that all of the window coordinates which we use are in pixel units.)
  147.  
  148.    GEM saves these values so that the program can get them later when
  149. processing  FULL requests.  Usually the best maximum size for a
  150. window is the entire desktop area, excepting the menu bar.  You can
  151. find this by asking {\tt wind\_get} for the working area of the desktop
  152. (handle zero, remember):
  153.  
  154. \begin{verbatim}
  155.    wind_get(0, WF_WXYWH, &xfull, &yfull, &wfull, &hfull);
  156. \end{verbatim}
  157.  
  158.    Note that {\tt WF\_WXYWH}, and all of the other mnemonics used in this
  159. article, are defined in the {\tt GEMDEFS.H} file in the ST Toolkit.
  160.  
  161.    The parts parameter of {\tt wind\_create} defines what features will be
  162. included in the window when it is drawn.  It is a word of single bit
  163. flags which indicate the presence/absence of each feature.  To
  164. request multiple features, the flags are {\em or-ed}\/ together. The flags'
  165. mnemonics and meanings are:
  166.  
  167. \begin{description}
  168.  
  169. \item[NAME] A one character high title bar at the top of the window.
  170.  
  171. \item[INFO] A second character line below the NAME.
  172.  
  173. \item[MOVER] This lets the user move the window around by {\em dragging}\/
  174.          in the NAME area.  NAME also needs to be defined.
  175.  
  176. \item[CLOSER] A square box at the upper left.  Clicking this control
  177. point asks that the window be removed from the screen.
  178.  
  179. \item[FULLER] A diamond at upper right.  Clicking this control point
  180. requests that the window grow to its maximum size, or  shrink back
  181. down if it is already big.
  182.  
  183. \item[SIZER] An arrow at bottom right.  Dragging the SIZER lets  the
  184. user choose a new size for the window.
  185.  
  186. \item[VSLIDE] defines a right-hand scroll box and bar for the window.
  187. By dragging the scroll bar, the user requests that the  window's
  188. {\em viewport}\/ into the information be moved.   Clicking on the gray box
  189. above the bar requests that  the window be moved up one {\em page}.
  190. Clicking below the  bar requests a down page movement.  You have to
  191. define  what constitutes a page or line in the context of your
  192. application.
  193.  
  194. \item[UPARROW] An arrow above the right scroll bar.  Clicking here
  195. requests that the window be moved up one {\em line\/}.  Sliders and arrows
  196. almost always appear together.
  197.  
  198. \item[DNARROW] An arrow below the right scroll bar.  Requests that  window
  199. be moved down a line.
  200.  
  201. \item[HSLIDE] These features are the horizontal equivalent of the
  202. VSLIDE above.  They appear at the bottom of the window.  Arrows
  203. LFARROW and RTARROW usually indicate {\em character\/} sized movement left
  204. and right.
  205. {\em Page}\/ sized movement has to be defined by each application.
  206. RTARROW and LFARROW are the horizontal equivalents of the
  207. vertical slider components.
  208.  
  209. \end{description}
  210.  
  211.    It is important to understand the correspondence between window
  212. features and event messages which are sent to the application by the
  213. GEM window manager.  If a feature is not included in a window's
  214. creation,  the user cannot perform the corresponding action, and your
  215. application will  never receive the matching message type.  For
  216. example, a window without a {\tt MOVER}\/ may not be dragged by the user,
  217. and your app will never get a {\tt WM\_MOVED}\/ message for that window.
  218.  
  219.    Another important principle is that the application itself is
  220. responsible for implementing the user's window action request when a
  221. message is received.  This gives the application a chance to accept,
  222. modify, or reject the user's request.
  223.  
  224.    As an example, if a {\tt WM\_MOVED}\/  message is received, it indicates that
  225. the user has dragged the window.  You might want to byte or word
  226. align the requested position before proceeding to move the window.
  227. The {\tt wind\_set} calls used to perform the actual movements will be
  228. described in a minute$\ldots$
  229.  
  230. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  231. \subsubsection{Open, Sesame!}
  232.  
  233.   The {\tt wind\_open} call is used to actually make the window
  234. appear on the screen.  It animates a {\em zoom box}\/ on the screen and
  235. then draws in the window's frame.  The calling sequence is:
  236.  
  237. \begin{verbatim}
  238.    wind_open(handle, x, y, w, h);
  239. \end{verbatim}
  240.  
  241.    The handle is the one returned by {\tt wind\_create}. 
  242. Parameters {\tt x}, {\tt y}, {\tt w},
  243. and {\tt h}\/ define the initial location and size of the window.  Note that
  244. these measurements INCLUDE all of the window frame parts which you
  245. have requested. To find out the size of the area inside the frame,
  246. you can use
  247.  
  248. \begin{verbatim}
  249.  wind_get(handle, WF_WXYWH, &inner_x, &inner_y, &inner_w, &inner_h);
  250. \end{verbatim}
  251.  
  252.    Whatever size you choose for the window display, it cannot be any
  253. larger than the full size declared in {\tt wind\_create}.
  254.  
  255.    Here is a good place to take note of a useful utility for calculating
  256. window sizes.  If you know the {\em parts list}\/ for a window, and its
  257. inner or outer size, you can find the other size with the {\tt wind\_calc}
  258. call:
  259.  
  260. \begin{verbatim}
  261.    wind_calc(parts, kind, input_x, input_y, input_w, input_h,
  262.              &output_x, &output_y, &output_w, &output_h);
  263. \end{verbatim}
  264.  
  265.    Kind is set to zero if the input coordinates are the inner area, and
  266. you are calculating the outer size.  Kind is one if the inputs are
  267. the outer size and you want the equivalent inner size.  Parts are
  268. just the same as in {\tt wind\_create}.
  269.  
  270.    There is one common bug in using {\tt wind\_open}.  If the {\tt NAME}\/
  271. feature  is
  272. specified, then the window title must be initialized BEFORE opening
  273. the window:
  274.  
  275. \begin{verbatim}
  276.    wind_set(handle, WF_NAME, ADDR(title), 0, 0);
  277. \end{verbatim}
  278.  
  279.    If you don't do this, you may get gibberish in the NAME area or the
  280. system may crash.   Likewise, if you have specified the INFO feature,
  281. you must make a {\tt wind\_set} call for {\tt WF\_INFO}\/ before opening the
  282. window.
  283.  
  284. Strings whose addresses are passed in the {\tt WF\_NAME}\/  and {\tt WF\_INFO}\/
  285. {\tt wind\_set} calls must be allocated in a static data area.  Since the
  286. AES remembers the addresses (not the characters), a disaster may result
  287. if the storage has been reused when the window manager next attempts to
  288. draw the window title area.
  289.  
  290.    Note  that {\tt ADDR()} specifies the 32-bit address of title.  This
  291. expression is  portable to other (Intel-based) GEM systems.  If you
  292. don't care about  portability, then \verb"&title[0]", or just \verb"title"
  293. alone will work fine on the ST.
  294.  
  295.  
  296. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  297. \subsubsection{Cleaning Up}
  298.   When you are done with a window, it should be closed
  299. and deleted.  The call
  300.  
  301. \begin{verbatim}
  302.    wind_close(handle);
  303. \end{verbatim}
  304.  
  305. takes the window off the screen, redraws the desktop underneath it,
  306. and animates a {\em zoom down}\/ box.  It doesn't delete the window's
  307. definition, so you can reopen it later.
  308.  
  309.    Deleting the window removes its definition from the system, and makes
  310. that handle available for reuse.  Always close windows before
  311. deleting,  or you may leave a {\em dead}\/ picture on the screen.  Also be
  312. sure to delete all  of your windows before ending the program, or
  313. your app may {\em eat}\/ window  handles.  The syntax for deleting a window
  314. is:
  315.  
  316. \begin{verbatim}
  317.    wind_delete(handle);
  318. \end{verbatim}
  319.  
  320.  
  321. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  322. \subsubsection{Those Fat Sliders}
  323.  
  324.   One of ST GEM's unique features is the
  325. proportional slider bar.  Unlike other windowing systems, this type
  326. of bar gives visual feedback on the fraction of a document which is
  327. being viewed, as well as the position within the document.  The
  328. catch, of course, is that you have two variables to maintain for each
  329. scroll bar: size and position.
  330.  
  331.    Both bar size and position range from 1~to~1000.  A bar size of 1000
  332. fills the slide box, and a value of one gets the minimum bar size.
  333. To compute the proper size, you can use the formula:
  334.  
  335. \begin{verbatim}
  336.    size = min(1000, 1000 * seen_doc / total_doc)
  337. \end{verbatim}
  338.  
  339.    {\tt seen\_doc}\/ and {\tt total\_doc}\/ are the visible and total size of
  340. the document
  341. respectively, in whatever units are appropriate.  As an example, if
  342. your window could show 20 lines of a 100 line text file, you should
  343. set a slider size of 200.  Since the window might be bigger than the
  344. total  document at some points, you need the maximum function.   If
  345. the document size is zero, force the slider size to 1000.  (Note: You
  346. will probably  need to do the computation above with 32-bit
  347. arithmetic to avoid overflow  problems.)
  348.  
  349.    Once you have computed the size, use the {\tt wind\_set} function to
  350. configure the scroll bar:
  351.  
  352. \begin{verbatim}
  353.    wind_set(handle, WF_VSLSIZE, size, 0, 0, 0);
  354. \end{verbatim}
  355.  
  356.    This call sets the vertical (right hand) scroll bar. 
  357. Use {\tt WF\_HSLSIZE}\/
  358. for the horizontal scroller.  All of these examples are done for the
  359. vertical dimension, but the principles are identical in the other
  360. direction.
  361.  
  362.    Bar positioning is a little tougher.   The most confusing aspect is
  363. that the 1--1000 range does not set an absolute position of the bar
  364. within the scroll box.  Instead, it positions the TOP of the bar
  365. within its possible range of variation.
  366.  
  367.    Let's look at our text file example again to make this clearer.  If
  368. there are always 20 lines of a 100 line file visible, then the top of
  369. the window must be always be somewhere between line 1 and line 81.
  370. This 80 line range is the actual freedom of movement of the window.
  371. So, if the window were actually positioned with its top at line 61,
  372. it would be at the three-quarter position within  the range, and we
  373. should set a scroll bar position of 750.  The actual  formula for
  374. computing the position is:
  375.  
  376. \begin{verbatim}
  377.    pos = 1000 * (top_wind - top_doc) / (total_doc - seen_doc)
  378. \end{verbatim}
  379.  
  380.    {\tt top\_wind}\/ and {\tt top\_doc}\/ are the top line in the current window and the
  381. whole document, respectively.  Obviously, if {\tt seen\_doc} is greater or
  382. equal to {\tt total\_doc}, you need to force a zero value for pos.  This
  383. calculation may seem rather convoluted the first time through, but is
  384. easy once you have done it.  When you have computed the position,
  385. \verb"wind_set" configures the scroll bar:
  386.  
  387. \begin{verbatim}
  388.    wind_set(handle, WF_VSLIDE, pos, 0, 0, 0);
  389. \end{verbatim}
  390.  
  391.    {\tt WF\_HSLIDE}\/ is the equivalent for horizontal scrolling.
  392.  
  393.    It is a good practice to avoid setting the slider size or position if
  394. they are already at the value which you need.  This avoids an
  395. annoying redraw flash on the screen when it is not necessary.  You
  396. can check on the current value of a slider parameter with {\tt wind\_get}:
  397.  
  398. \begin{verbatim}
  399.    wind_get(handle, WF_VSLIDE, &curr_value, &foo, &foo, &foo);
  400. \end{verbatim}
  401.  
  402.    {\tt foo}\/ is a dummy variable which needs to be there, but is not used.
  403. Substitute {\tt WF\_VSLIDE}\/ with whatever parameter you are checking.
  404.  
  405.    One philosophical note on the use of sliders:  It is probably best to
  406. avoid the use of both sliders at once unless it is clearly
  407. appropriate to the type of data which is being viewed.
  408.  
  409.    Since Write and Paint programs make use of the sheet-of-paper
  410. metaphor, moving the window around in both dimensions is reasonable.
  411. However, if the data is more randomly organized, such as a tableau of
  412. icons, then it is probably better to only scroll in  the vertical
  413. dimension and {\em reshuffle}\/ if the window's width is changed. Then the
  414. user only needs to manipulate one control to find information which
  415. is off-screen.  Anyone who has had trouble finding a file or folder
  416. within a Desktop window will recognize this problem.
  417.  
  418.  
  419. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  420. \subsection{Excelsior!}
  421.  
  422.   The file for this chapter is {\tt GEMCL02.C}.  All references  to non-GEM
  423. routines in this column refer to this file.  Please note that  these
  424. files will not contain entire programs.  Instead, they consist of
  425. small pieces of utility code which you may use and modify in your
  426. own  programs.
  427.  
  428. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  429. \subsection{Redrawing windows}
  430.  
  431.   One of the most misunderstood parts of GEM is the correct method for
  432. drawing within a window.  Most requests for redrawing are generated
  433. by the GEM system, and arrive as messages (read with {\tt evnt\_multi})
  434. which contain the handle of the window, and the screen rectangle
  435. which is  {\em dirty}\/ and needs to be redrawn.
  436.  
  437.   Screen areas may become dirty as a result of windows being closed,
  438. sized down, or moved, thus {\em exposing}\/ an area underneath.  The
  439. completion of  a dialog, or closing of a desk accessory may also free
  440. up a screen area which needs to be redrawn.  When GEM detects the
  441. presence of a dirty rectangle,  it checks its list of open windows,
  442. and sends the application a redraw message  for each of its windows
  443. which intersects the dirty area.
  444.  
  445.   GEM does not {\em clip}\/ the rectangle which it sends to  the application;
  446. that is, the rectangle may not lie entirely within the  portion of
  447. the window which is exposed on the screen.  It is the job of the
  448. application to determine in what portion of the rectangle it may
  449. safely draw.   This is done by examining the {\em rectangle list}\/
  450. associated with the window.
  451.  
  452.   A rectangle list is maintained by GEM for each active window.  It
  453. contains the portions of the window's interior which are exposed,
  454. i.e., topmost, on the screen and within which the app may draw.
  455.  
  456.   Let's consider an example to make this clear.  Suppose an app has
  457. opened two windows, and there are no desk accessory windows open. The
  458. window which is topmost will  always have only one rectangle in its
  459. list.  If the two are separate on the  screen, then the second window
  460. will also have one rectangle.  If they overlap,  then the top window
  461. will "break" the rectangle of the bottom one.  If the  overlap is at
  462. a corner, two rectangles will be generated for the bottom window.  If
  463. the overlap is on a side only, then three rectangles are required to
  464. cover  the exposed portion of the bottom window.  Finally, if the
  465. first window is  entirely within the second, it requires four
  466. rectangles in the list to tile the second window.
  467.  
  468.   Try working out a few rectangle examples with pencil and paper to
  469. get the feel of it.  You will see that the possible combinations with
  470. more  than two windows are enormous.  This, by the way, is the reason
  471. that GEM does  not send one message for each rectangle on the list:
  472. With multiple windows,  the number of messages generated would
  473. quickly fill up the application's message queue.
  474.  
  475.   Finally, note that every app MUST use this method, even if it only
  476. uses a single window, because there may be desk accessories with
  477. their own  windows in the system at the same time.  If you do not use
  478. the rectangle lists, you may overwrite an accessory's window.
  479.  
  480.   One more note on rectangles: although AES intersects the rectangles 
  481. with the window work area, parts of a rectangle may be off screen because
  482. the window is partially off screen. Redrawing may then lead to interesting
  483. results. Intersecting a rectangle with the screen
  484. {\tt GRECT} before redrawing will solve this problem.
  485.  
  486. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  487. \subsection{Into the bits}
  488.  
  489.   First, we should note that the message type for a  redraw request is
  490. {\tt WM\_REDRAW}, which is stored in \verb"msg[0]", the first location of the
  491. message returned by {\tt evnt\_multi}.  The window handle is stored in
  492. \verb"msg[3]".  These locations are the same for all of the message types
  493. being discuss.  The rectangle which needs to be redrawn is stored in
  494. \verb"msg[4]" through \verb"msg[7]".
  495.  
  496.   Now let's examine the sample redraw code in more detail. The redraw
  497. loop is bracketed with mouse off and mouse on calls.  If you forget
  498. to do  this, the mouse pointer will be over-written if it is within
  499. the window and  the next movement of the mouse will leave a
  500. rectangular blotch on the screen  as a piece of the {\em old}\/ screen is
  501. incorrectly restored.
  502.  
  503.   The other necessary step is to set the window update flag.  This
  504. prevents the menu manager from dropping a menu on top of the screen
  505. portion being redrawn.  You must release this flag at the end of the
  506. redraw, or the you will be unable to use any menus afterwards.
  507.  
  508.   The window rectangles are retrieved using a get-first, get-next
  509. scheme which will be familiar if you have used the GEM DOS or PC-DOS
  510. wildcard file calls.  The end of the rectangle list has been reached
  511. when both the width and height returned are zero.  Since some part of
  512. a  window might be off-screen (unless you have clamped its position -
  513. see below), the retrieved rectangle is intersected with the desktop's
  514. area,  and then with the screen area for which a redraw was
  515. requested.
  516.  
  517.   Now you have the particular area of the screen in which it is  legal
  518. to draw.  Unless there is only one window in your application, you
  519. will have to test the handle in the redraw request to figure out what
  520. to  put in the rectangle.
  521.  
  522.   Depending on the app, you may be drawing an AES  object tree, or
  523. executing VDI calls, or some combination of the two.  In  the AES
  524. case, the computed rectangle is used to specify the bounds of the
  525. {\tt objc\_draw}.  For VDI work, the rectangle is used to set the clipping
  526. area before executing the VDI calls.
  527.  
  528.  
  529. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  530. \subsection{A small confession}
  531.  
  532.   At the beginning of this discussion, I  deliberately omitted one
  533. class of redraws: those initiated by the application  itself.
  534.  
  535.   In some cases a part of the screen must be redrawn immediately to
  536. give feedback to the user following a keystroke, button, or mouse
  537. action.   In these cases, the application could call {\tt do\_redraw}
  538. directly, without  waiting for a message.
  539.  
  540.   The only time you can bypass {\tt do\_redraw}, and draw  without walking the
  541. rectangle list, is when you can be sure that the target  window is on
  542. top, and that the figure being drawn is entirely contained  within it.
  543.  
  544.   In many cases, however, an application initiated redraw happens
  545. because of a computed change, for instance, a spreadsheet update, and
  546. its timing is not crucial.  In this instance, you may wish to have
  547. the  app send ITSELF a redraw request.
  548.  
  549.   The main advantage of this approach  is that the AES is smart enough
  550. to see if there is already a redraw request for the same window in
  551. the queue, and, if so, to merge the requests by  doing a union of
  552. their rectangles.  In this fashion, the {\em blinky}\/ appearance of
  553. multiple redraws is avoided, without the need to include logic for
  554. merging redraws within the program.
  555.  
  556.   A utility routine for sending the {\em self-redraw}\/ is included in
  557. {\tt GEMCL02.C}.
  558.  
  559.      A number of developers reported that they were unable to get
  560. the  self-redraw  technique to  work.
  561. This is usually due to a bug in the {\tt appl\_init} binding in Alcyon C.
  562. The  value  returned from the function,  which would  normally  be
  563. assigned  to \verb"gl_apid",  is coming back as garbage.   To work around
  564. the problem,  declare
  565.  
  566. \verb"EXTERN WORD gl_apid;"  
  567.  
  568. \noindent in your program and {\em do not}\/ assign the value from
  569. {\tt appl\_init}. The binding WILL make  the assignment.
  570.  
  571.  
  572. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  573. \subsection{Window Control Requests}
  574.  
  575.   An application is notified by the AES, via the message system, when
  576. the user manipulates one of the window control points.  Remember that
  577. you must have specified each control point when the window was
  578. created, or will not receive the associated control message.
  579.  
  580.   The most important thing to understand about window control is that
  581. the change which the user requested does not take place until the
  582. application forwards it to the AES.  While this makes for a little
  583. extra work,  it gives the program a chance to intervene and validate
  584. or modify the request to suit.
  585.  
  586.   A second thing to keep in mind is that not all window updates cause a
  587. redraw request to be generated for the window, because the AES
  588. attempts to save time with raster moves on the screen.
  589.  
  590.   Now let's look at each window control request in detail.  The
  591. message code for a window move is {\tt WM\_MOVED}.  If you are willing to
  592. accept  any such request, just do:
  593.  
  594. \begin{verbatim}
  595.   wind_set(wh, WF_CXYWH, msg[4], msg[5], msg[6], msg[7]);
  596. \end{verbatim}
  597.  
  598.   (Remember that {\tt wh}, the window handle, is always in \verb"msg[3]").
  599. \vskip.2cm
  600.  
  601.   The AES will not request a redraw of the window following this call,
  602. unless the window is being moved from a location which is partially
  603. {\em off-screen}. Instead, it will do a {\em blit}\/ (raster copy) of the
  604. window and its contents to the new location without intervention by
  605. the app.
  606.  
  607.   There are two constraints which you may often wish to apply to  the
  608. user's move request.  The first is to force the new location to lie
  609. entirely within the desktop, rather than partially off-screen.  You
  610. can do this with the {\tt rc\_constrain} utility by executing:
  611.  
  612. \begin{verbatim}
  613.   rc_constrain(&full, &msg[4]);
  614. \end{verbatim}
  615.  
  616. \noindent before making the {\tt wind\_set} call.  ({\tt full}\/ is assumed to contain
  617. the desktop dimensions.) 
  618.  
  619.   The second common constraint is to {\em snap}\/ the x-dimension location of
  620. the new location to a word boundary.  This operation will speed up
  621. GEM's {\em blit}\/ because no shifting or masking will need to be done
  622. when moving the window.  To perform this operation, use {\tt align()}
  623. before the  {\tt wind\_set} call:
  624.  
  625. \begin{verbatim}
  626.   msg[4] = align(msg[4], 16);
  627. \end{verbatim}
  628.  
  629.   Calling {\tt wind\_set} with an x-coordinate of -1
  630. will cause the left border of the window not to be displayed, which is 
  631. especially convenient when snapping to word boundaries.
  632.  
  633.   The message code for a window size request is {\tt WM\_SIZED}.  Again, if
  634. you are willing to accept any request, you can just {\em turn it around}\/
  635. with the same {\tt wind\_set} call as given for {\tt WM\_MOVED}.
  636.  
  637.   Actually, GEM enforces a couple of constraints on sizing.  First, the
  638. window may not be sized off screen.  Second, there is a minimum
  639. window size which is dependent on the window components specified
  640. when it was created.  This prevents features like scroll arrows from
  641. being squeezed into oblivion.
  642.  
  643.   The most common application constraint on sizing is to snap the size
  644. to horizontal words (as above) and/or vertical character lines.  In
  645. the latter case, the vertical dimension of the output font is used
  646. with {\tt align()}.
  647.  
  648.   Also,  be aware that the size message which you receive specifies the
  649. EXTERNAL  dimensions of the window.  To assure an {\em even}\/ size for the
  650. INTERNAL dimensions, you must make a {\tt wind\_calc} call to compute them,
  651. use {\tt align()} on the computed values, back out the corresponding
  652. external dimensions with the reverse {\tt wind\_calc}, and then make the
  653. {\tt wind\_set} call with this set of values.
  654.  
  655.   A window resize will only cause a redraw request for the window if
  656. the size is being increased in at least one dimension.  This is
  657. satisfactory for most applications, but if you must {\em reshuffle}\/ the
  658. window after a  size-down, you should send yourself a redraw (as
  659. described above) after you make the {\tt wind\_set} call.  This will
  660. guarantee that the display is updated correctly.  Also note that the
  661. sizing or movement of one window may cause redraw requests to be
  662. generated for other windows which are uncovered by the change.
  663.  
  664.   The window full request, with code {\tt WM\_FULLED}, is actually a toggle.
  665. If the window is already at its full size (as specified in the
  666. {\tt wind\_create}), then this is a request to shrink to its previous size.
  667. If the window is currently small, then the request is to grow to full
  668. size.
  669.  
  670.   Since the AES records the current, previous, and maximum window size,
  671. you can use  {\tt wind\_get} calls to determine which situation pertains.
  672. The {\tt hndl\_full} utility in {\tt GEMCL2.C} (modified from Doodle), shows
  673. how to do this.
  674.  
  675.   The {\em zoom box}\/ effects when changing size are optional, and can be
  676. removed  to speed things up.  Again, if the window's size is
  677. decreasing, no redraw is  generated, so you must send yourself one if
  678. necessary.  You should not have  to perform any constraint or {\em snap}\/
  679. operations here, since (presumably) the  full and previous sizes have
  680. had these checks applied to them already.
  681.  
  682.   The {\tt WM\_CLOSED} message is received when the close box is clicked. What
  683. action you perform depends on the application.  If you want to remove
  684. the window, use {\tt wind\_close} as described earlier.  In many
  685. applications, however, the close message may indicate that a file is
  686. to be saved, or a directory or editing level is to be closed.  In
  687. these cases, the message is used to trigger this action before or
  688. instead of the {\tt wind\_close}.  (Folders on the Desktop are an example of
  689. this situation.)
  690.  
  691.   The {\tt WM\_TOPPED}\/ message indicates that the AES wants to bring the
  692. indicated window to the {\em top}\/ and make it active.  This happens if
  693. the user clicks within a window which is not on top, or if the
  694. currently topped window is closed by its application or desk
  695. accessory.  Normally, the application should respond to this message
  696. with:
  697.  
  698. \begin{verbatim}
  699.   wind_set(wh, WF_TOP, 0, 0);
  700. \end{verbatim}
  701.  
  702. \noindent and allow the process to complete.
  703.  
  704.   In a few instances, a window may be used in an output only mode, such
  705. as a status display, with at least one other window present for
  706. input.  In this case, a {\tt WM\_TOPPED}\/ message for the status window may
  707. be ignored.  In all other cases, you must handle the {\tt WM\_TOPPED}\/ 
  708. message even if your application has only one window: Invocation of a
  709. desk accessory could always place another window on top.  If you fail
  710. to do so, subsequent redraws for your window may not be processed
  711. correctly.
  712.  
  713.  
  714. % bis hier wurden Funktionen in sans serif gesetzt
  715. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  716. \subsection{Window Slider Messages}
  717.  
  718.   If you specify all of the slider bar parts for your window, you may
  719. receive up to five different message types for each of the two sets
  720. of sliders.  To simplify things a little, I will discuss everything
  721. in terms of the vertical (right hand side) sliders.  If you are also
  722. using the horizontal sliders, the same techniques will work, just use
  723. the alternate mnemonics.
  724.  
  725.   The \verb"WM_VSLID" message indicates that the user has dragged the slider
  726. bar within its box, indicating a new relative position within the
  727. document.  Along with the window handle, this message includes the
  728. relative position between 1 and 1000 in \verb"msg[4]".
  729.  
  730.   Recall from the previous discussion that this interval corresponds
  731. to the "freedom of movement" of the slider. If you want to accept the
  732. user's request, just make the call:
  733.  
  734. \begin{verbatim}
  735.   wind_set(wh, WF_VSLIDE, msg[4], 0, 0, 0);
  736. \end{verbatim}
  737.  
  738.   (Corresponding horizontal mnemonics are \verb"WM_HSLID" and \verb"WF_HSLIDE").
  739.  
  740.   Note that this \verb"wind_set" call will not cause a redraw message to be
  741. sent.  You must update the display to reflect the new scrolled
  742. position, either by executing a redraw directly, or by sending
  743. yourself a message.
  744.  
  745.   If the document within the window has some structure, you may not
  746. wish to accept all slider positions.  Instead you may want to force
  747. the scroll position to the nearest text line (for instance).  Using
  748. terms defined in the last column, you may convert the slider position
  749. to "document units" with:
  750.  
  751. \begin{verbatim}
  752.   top_wind = msg[4] * (total_doc - seen_doc) / 1000 + top_doc
  753. \end{verbatim}
  754.  
  755.   (This will probably require 32-bit arithmetic).
  756.  
  757.   After rounding off or otherwise modifying the request, convert it
  758. back to slider units and make the \verb"WF_VSLIDE" request.
  759.  
  760.   The other four slider requests all share one message code:
  761. \verb"WM_ARROWED".  They are distinguished by sub-codes stored in \verb"msg[4]":
  762. \verb"WA_UPPAGE", \verb"WA_DNPAGE", \verb"WA_UPLINE", and \verb"WA_DNLINE".  These are produced
  763. by clicking above and below the slider, and on the up and down
  764. arrows, respectively.  (I have no idea why sub-codes were used in
  765. this one instance.)  The corresponding horizontal slider codes are:
  766. \verb"WA_LFPAGE", \verb"WA_RTPAGE", \verb"WA_LFLINE", and \verb"WA_RTLINE".
  767.  
  768.   What interpretation you give to these requests will depend on  the
  769. application.  In the most common instance, text documents, the
  770. customary method is to change the top of window position (top\_wind)
  771. by  one line for a \verb"WA_UPLINE" or \verb"WA_DNLINE", and by {\tt seen\_doc} (the
  772. number of lines in the window) for a \verb"WA_UPPAGE" or \verb"WA_DNPAGE".
  773.  
  774.   After making the change, compute a new slider position, and make the
  775. \verb"wind_set" call as given above.  If the document's length is not an
  776. even multiple of "lines" or "pages" you will have to be careful that
  777. incrementing or  decrementing {\tt top\_wind} does not exceed its range of
  778. freedom:
  779. {\tt top\_doc} to ({\tt top\_doc} + {\tt total\_doc} - {\tt seen\_doc}).
  780.  
  781.   If you have such an odd size document, you will also have to make a
  782. decision on whether to violate the line positioning rule so that the
  783. slider may be put at its bottom-most position, or to follow the rule
  784. but make it impossible to get the slider to the extreme of its range.
  785.  
  786. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  787. \subsection{A common bug}
  788.  
  789.   It is easy to forget that user clicks are not the only things that
  790. affect slider position.  If the window size changes as a result of a
  791. \verb"WM_SIZED" or \verb"WM_FULLED" message, the app must also  update its sliders
  792. (if they are present).  This is a good reason to keep the top of
  793. window information in "document units".
  794.  
  795.   You can just redo the position calculation with the new {\tt seen\_doc}\/
  796. value, and call \verb"wind_set".  Also remember that changing the size of
  797. the underlying document  (adding or deleting a bottom line, for
  798. instance) must also cause the sliders  to be adjusted.
  799.  
  800. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  801. \subsection{Dept.~of Dirty Tricks}
  802.  
  803.   There are two remaining window calls which are useful to advanced
  804. programmers.  They require techniques which I have not yet discussed,
  805. so you may need to file them for future reference.
  806.  
  807.   The AES maintains a quarter-screen sized buffer which is used to save
  808. the area under alerts and menu drop-downs.  It is occasionally useful
  809. for the application to gain access to this buffer for its own use in
  810. saving screen areas with raster copies.  To do so, use:
  811.  
  812. \begin{verbatim}
  813.   wind_get(0, WF_SCREEN, &loaddr, &hiaddr, &lolen, &hilen);
  814. \end{verbatim}
  815.  
  816.   {\tt hiaddr} and {\tt loaddr} are the top and bottom 16-bits (respectively) of
  817. the  32-bit address of the buffer.  {\tt hilen} and {\tt lolen} are the two
  818. halves of  its length.
  819.  
  820.   Due to a preculiarity of the binding you have to reassemble  these
  821. pieces before using them.  (The actual value of \verb"WF_SCREEN" is 17; this
  822. does not appear in some versions of the {\tt GEMDEFS.H} file.)
  823.  
  824.   If you use this buffer, you MUST prevent menus from dropping down by
  825. using either the \verb"BEG_UPDATE" or \verb"BEG_MCTRL" \verb"wind_update" calls.  Failure
  826. to do so will result in your data being destroyed.  Remember to use
  827. the matching \verb"wind_update": \verb"END_UPDATE" or \verb"END_MCTRL",
  828. when you are done.
  829.  
  830.   The other useful call enables you to replace the system's desktop
  831. definition with a resource of your choosing.  The call:
  832.  
  833. \begin{verbatim}
  834.   wind_set(0, WF_NEWDESK, tree, 0, 0);
  835. \end{verbatim}
  836.  
  837. where {\tt tree}\/ is the 32-bit address of the object tree, will cause the
  838. AES to draw your definition instead of the usual gray or green
  839. background. Not only that, it will continue to redraw this tree with
  840. no intervention on your part.
  841.  
  842.   Obviously, the new definition must be carefully built to fit the
  843. desktop area exactly or garbage will be left around the edges.  For
  844. the truly sophisticated, a user-defined object could be used in this
  845. tree, with the result that your application's code would be entered
  846. from the AES whenever the desktop was redrawn.  This would allow you
  847. to put VDI pictures or complex images onto the desktop background.
  848.  
  849.   This concludes our tour of GEM's basic window management techniques.
  850. There have been some unavoidable glimpses of paths not yet taken
  851. (forward references), but we will discuss those soon.
  852.  
  853.   In the next chapter, we will take a look at techniques for handling
  854. simple dialog boxes, and start exploring the mysteries of resources
  855. and object trees.
  856.  
  857.  
  858. \newpage
  859.  
  860. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  861. \section{The Dialog Handler}
  862.  
  863. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  864. \subsection{A meaningful dialog}
  865.  
  866.    We will now start an exploration of ST GEM's dialog
  867. handler.  I will discuss basic system calls for presenting the
  868. dialog, and then continue with techniques for initializing and
  869. reading on/off button and "radio" button objects.  We  will also take
  870. some short side-trips into the operation of the GEM Resource
  871. Construction Set to assist you in building these dialogs.
  872.  
  873.    There are a number of short C routines which accompany this chapter.
  874. These are found in {\tt GEMCL03.C}.
  875.  
  876. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  877. \subsection{Defining terms}
  878.  
  879.    A dialog box is an "interactive form" in which the user may enter
  880. text and indicate selections by pointing with the mouse. Dialogs in
  881. GEM are "modal", that is, when a dialog is activated other screen
  882. functions such as menus and  window controls are suspended until the
  883. dialog is completed.
  884.  
  885.    In most cases, the visual structure of a GEM dialog is specified
  886. within your application's resource file.  The GEM Resource
  887. Construction Set (RCS) is used to build a picture of the dialog.
  888.  
  889.    When the RCS writes out a resource, it converts that picture into a
  890. tree of GEM drawing objects and stores this data structure within the
  891. resource.  Before your application can  display the dialog, it must
  892. load this resource file and find the  address of the tree which
  893. defines the dialog.
  894.  
  895.    To load a resource, the AES checks its size and allocates memory for
  896. the load.  It then reads in the resource, adjusting internal pointers
  897. to reflect the load address.  Finally, the object sizes stored in the
  898. resource are converted from characters to pixels using the system
  899. font size.
  900.  
  901.    (A note for those with Macintosh experience:  Although Mac and GEM
  902. resources share a name, there are fundamental differences which can
  903. be misleading.  A Mac resource is a fork within a file; a GEM
  904. resource is a TOS file by itself.  Mac resources may be paged in and
  905. out of memory; GEM resources are monolithic.  GEM resources are
  906. internally tree structured; Mac resources are not.  Finally, Mac
  907. resources include font information, while ST GEM does this with font
  908. loading at the VDI level.)
  909.  
  910.    The resource load is done with the GEM AES call:
  911.  
  912. \begin{verbatim}
  913.    ok = rsrc_load(ADDR("MYAPP.RSC"));
  914. \end{verbatim}
  915.  
  916.    {\tt MYAPP}\/ should be replaced with the name of your program. Resources
  917. conventionally have the same primary name as their application, with
  918. the RSC extent name instead of PRG.  The {\tt ok}\/ flag returned by
  919. \verb"rsrc_load" will be FALSE is anything went wrong during the load.
  920.  
  921.    The most common causes of failure are the resource not being in the
  922. application's subdirectory, or lack of sufficient memory for GEM to
  923. allocate space for the resource.  If this happens, you must terminate
  924. the program immediately.
  925.  
  926.    Once you have loaded the resource, you find the address of a dialog's
  927. object tree with:
  928.  
  929. \begin{verbatim}
  930.    rsrc_gaddr(R_TREE, MYDIALOG, &tree);
  931. \end{verbatim}
  932.  
  933. {\tt tree} is a 32-bit variable which will receive the address of the root
  934. node of the tree.
  935.  
  936.    The mnemonic \verb"MYDIALOG" should be replaced with the name you gave your
  937. dialog when defining it in the RCS.  At the same time that it writes
  938. the resource, RCS generates a corresponding {\tt .H} file containing tree
  939. and object names.  In order to use these mnemonics within your
  940. program, you must include the name file in your compile:  
  941.  
  942. \begin{verbatim}
  943. #include "MYAPP.H"
  944. \end{verbatim}
  945.  
  946. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  947. \subsection{Bug Alert!}
  948.  
  949.    When using the DRI/Alcyon C compiler, {\tt .H} files must be in the
  950. compiler's home directory or they will not be found.  This is
  951. especially annoying using a two floppy drive ST development system.
  952. The only way around this is to explicitly  reference an alternate
  953. disk in the \verb"#include", for instance:  \verb"B:MYAPP.H"
  954.  
  955.    Now that the address of the dialog tree has been found, you are ready
  956. to display it.  The standard (and minimal) sequence for doing so is
  957. given in routine \verb"hndl_dial()" in {\tt GEMCL03.C}.  We will now walk
  958. through each step in this procedure.
  959.  
  960.    The \verb"form_center" call establishes the location of the dialog on the
  961. screen.  Dialog trees generated by the RCS have an undefined origin
  962. (upper-left corner).
  963.  
  964.    \verb"Form_center" computes the upper-left location necessary to center the
  965. dialog on the screen, and inserts it into the \verb"OB_X" and \verb"OB_Y" fields of
  966. the \verb"ROOT" object of the tree.  It also computes the screen rectangle
  967. which the dialog will occupy on screen and writes its pixel
  968. coordinates into variables {\tt xdial}, {\tt ydial}, {\tt wdial}, and {\tt hdial}.
  969.  
  970.    There is one peculiarity of \verb"form_center" which occasionally causes
  971. trouble.  Normally the rectangle returned in {\tt xdial}, etc., is exactly
  972. the same size as the basic dialog box.
  973.  
  974.    However, when the \verb"OUTLINED" enhancement has been specified for the
  975. box, \verb"form_center" adds a three pixel margin to the rectangle returned.
  976. This causes the screen area under the outline to be correctly redrawn
  977. later (see below).  Note that \verb"OUTLINED" is part of the standard dialog
  978. box in the RCS.  Other enhancements, such as \verb"SHADOWED" or "outside"
  979. borders are NOT handled in this fashion, and you must compensate  for
  980. them in your code.
  981.  
  982.    The next part of the sequence is a \verb"form_dial" call with a zero
  983. parameter.  This reserves the screen for the dialog action about to
  984. occur. Note that the C binding given for \verb"form_dial" in the DRI
  985. documents is in error: there are nine parameters, not five.  The
  986. first set of xywh arguments is actually used with \verb"form_dial" calls 1
  987. and 2 only, but place holders must be supplied in all cases.
  988.  
  989.    The succeeding \verb"form_dial" call (parameter one) animates a "zoom box"
  990. on the screen which moves and grows from the first screen rectangle
  991. given to the second rectangle, where the dialog will be displayed.
  992.  
  993.    The use of this call is entirely optional.  In choosing whether to
  994. use it or not, you should consider whether the origin of the "zoom"
  995. is relevant to the  operation.  For instance, a zoom from the menu
  996. bar is relatively meaningless, while a zoom from an object about to
  997. be edited in the dialog provides visual feedback to the user, showing
  998. whether the correct object was chosen.
  999.  
  1000.    If the origin is not relevant, then the zoom is just a time-waster.
  1001. If  you decide to include these effects, consider a "preferences"
  1002. option in  your app which will allow the experienced and jaded user
  1003. to turn them off in the interests of speed.
  1004.  
  1005.    The \verb"objc_draw" call actually displays the dialog on the screen. Note
  1006. that the address of the tree, the beginning drawing object, and the
  1007. drawing depth are passed as arguments, as well as the rectangle
  1008. allotted for the dialog.
  1009.  
  1010.    In general, dialogs (and parts of dialogs) are  ALWAYS drawn
  1011. beginning at the ROOT (object zero).  When you want to draw  only a
  1012. portion of the dialog, adjust the clipping rectangle, but not the
  1013. object number.  This ensures that the background of the dialog is
  1014. always  drawn correctly.
  1015.  
  1016.    The \verb"objc_xywh()" utility in the listing can be used to find the
  1017. clipping rectangle for any object within a dialog, though you may
  1018. have to allow an extra margin is you have used shadows, outlines, or
  1019. outside borders with the object.
  1020.  
  1021.    Calling \verb"form_do" transfers control to the AES, which animates the
  1022. dialog for user interaction.  The address of the dialog tree is
  1023. passed as a parameter.  The second paramter is the number of the
  1024. editable object at which the text cursor will first be positioned.
  1025. If you have no text fields, pass a zero.  Note that again the DRI
  1026. documents are in error: passing a -1 default may crash the system.
  1027. Also be careful that the default which you specify is actually a text
  1028. field; no error checking is performed.
  1029.  
  1030.    The \verb"form_do" call returns the number of the object on which the user
  1031. clicked to terminate the dialog.  Usually this is a button type
  1032. object with the \verb"EXIT" and \verb"SELECTABLE" attributes set.  Setting the
  1033. \verb"DEFAULT" attribute as well will cause an exit on that object is a
  1034. carriage return is struck while in the dialog.
  1035.  
  1036.    If the top bit of the return is set, it indicates that  the exit
  1037. object had the \verb"TOUCHEXIT" attribute and was selected with a
  1038. double-click.  Since very few dialogs use this combination, the
  1039. sample code simply masks off the top bit.
  1040.  
  1041.    The next \verb"form_dial" call reverses the "zoom box", moving it from the
  1042. dialog's location back to the given x,y,w,h.  The same cautions apply
  1043. here as above.
  1044.  
  1045.    The final \verb"form_dial" call tells GEM that the dialog is complete, and
  1046. that the screen area occupied by the dialog is now considered "dirty"
  1047. and needs to be redrawn.  Using the methods described in the previous
  1048. chapter, GEM then sends redraws to all windows which were overlaid,
  1049. and does any necessary redrawing of the menu or desktop itself.
  1050.  
  1051.    There is one notable "feature" of \verb"form_dial(3)":  It always redraws
  1052. an area which is two pixels wider and higher than your request!  This
  1053. was probably included to make sure that drop-shadows were cleaned up,
  1054. and is usually innocuous.
  1055.  
  1056. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1057. \subsection{A handy trick}
  1058.  
  1059.    Use of the \verb"form_dial(3)" call is not limited to dialogs.  You can
  1060. use it to force the system to redraw any part of the screen.  The
  1061. advantage of this method is that the redraw area need not lie
  1062. entirely within a window, as was necessary with the {\tt send\_redraw}\/
  1063. method detailed in the last chapter.  A disadvantage is that this
  1064. method is  somewhat slower, since the AES has to decide who gets the
  1065. redraws.
  1066.  
  1067. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1068. \subsection{Clean up}
  1069.  
  1070.    As a last step, you need to clear the \verb"SELECTED" flag in the object
  1071. which was clicked.  If you do not do this, the object will  be drawn
  1072. inverted the next time you call the dialog.  You could clear the flag
  1073. with the GEM \verb"objc_change" call, but it is inefficient since you do
  1074. not need to redraw the object.
  1075.  
  1076.    Instead, use the \verb"desel_obj()" code in the  listings, which modifies
  1077. the object's \verb"OB_STATE" field directly.  Assuming  that {\tt ret\_obj}
  1078. contains the exit object returned by \verb"hndl_dial", the call:
  1079.  
  1080. \begin{verbatim}
  1081.    desel_obj(tree, ret_obj);
  1082. \end{verbatim}
  1083.  
  1084. will do the trick.
  1085.  
  1086. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1087. \subsection{Recap}
  1088.  
  1089.    The basic dialog handling method I have described contains three
  1090. steps: initialization ({\tt rsrc\_gaddr}\/), dialog presentation ({\tt hndl\_dial}\/),
  1091. and cleanup ({\tt desel\_obj}\/).
  1092.  
  1093.    As we build more advanced dialogs, these same basic steps will be
  1094. performed, but they will grow more complex. The initialization will
  1095. include setting up proper object text and states, and the cleanup
  1096. phase will also interrogate the final states of objects to find out
  1097. what the user did.
  1098.  
  1099. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1100. \subsection{Button, button}
  1101.  
  1102.    The simple dialogs described above contain only exit buttons as
  1103. active objects.  As such, they are little more than glorified alert
  1104. boxes.
  1105.  
  1106.    We will now increase the complexity a little by considering non-exit
  1107. buttons.  These are constructed by setting the \verb"SELECTABLE" attribute
  1108. on a button object.  At run-time, such an object will toggle its
  1109. state between selected (highlighted) and non-selected  whenever the
  1110. user clicks on it.  (You can set the \verb"SELECTABLE" attribute  of other
  1111. types of objects and use them instead of actual buttons, but  be sure
  1112. that the user will be able to figure out what you intend!)
  1113.  
  1114.    Having non-exit buttons forces us to consider the problem of
  1115. initializing them before the dialog, and interrogating and resetting
  1116. them afterward.
  1117.  
  1118.    Since a button is a toggle, it is usually associated with a flag
  1119. variable in the program.  As part of the initialization, you should
  1120. test the flag variable, and if true call:
  1121.  
  1122. \begin{verbatim}
  1123.    sel_obj(tree, BTNOBJ);
  1124. \end{verbatim}
  1125.  
  1126. which will cause the button to appear highlighted when the dialog is
  1127. first drawn.  \verb"Sel_obj()" is in the listing.  \verb"BTNOBJ" is replaced with
  1128. the  name you gave your button when you defined it in the RCS.  Since
  1129. the button starts out deselected, you don't have to do anything if
  1130. your flag variable is false.
  1131.  
  1132.    After the dialog has completed, you need to check the object's state.
  1133. The \verb"selectp()" utility does so by masking the \verb"OB_STATE" field.  You can
  1134. simply assign the result of this test to your flag variable, but be
  1135. sure that the dialog was exited with an OK button, not with a CANCEL!
  1136. Again, remember to clean up the button with \verb"desel_obj()". (It's often
  1137. easiest to deselect all buttons just before you leave the dialog
  1138. routine, regardless of the final dialog state.)
  1139.  
  1140. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1141. \subsection{Who's got the button?}
  1142.  
  1143.    Another common use of buttons in a  dialog is to select one of a set
  1144. of possible options.  In GEM, such objects are called radio buttons.
  1145. This term recalls automobile radio tuners where pushing in one button
  1146. pops out any others.  In like fashion, selecting any one of a set of
  1147. radio buttons automatically deselects all of the others.
  1148.  
  1149.    To use the radio button feature, you must do some careful work with
  1150. the Resource Construction Set.
  1151.  
  1152.    First, each member of a set of  radio buttons must be children of the
  1153. same parent object within the  object tree. To create this structure,
  1154. put a hollow box type object in the  dialog, make it big enough to
  1155. hold all of the buttons, and then put the buttons into the box one at
  1156. a time.
  1157.  
  1158.    By nesting the buttons within the  box object, you force them to be
  1159. its children.  Each of the buttons must have both the \verb"SELECTABLE" and
  1160. \verb"RADIO BUTTON" attributes set.  When you are done, you may make the
  1161. containing box invisible by setting its border to zero, {\em but do not
  1162. FLATTEN it!}
  1163.  
  1164.    Since each radio button represents a different option, you must
  1165. usually assign a name to each object.  When initializing the dialog,
  1166. you must check which option is currently set, and turn on the
  1167. corresponding button only.  A chain of if-then-else structures
  1168. assures that only one button will be selected.
  1169.  
  1170.    At the conclusion of the dialog, you must check each button with
  1171. \verb"selectp()" and make the appropriate adjustments to internal variables.
  1172. Again, an if-then-else chain is appropriate since only one button may
  1173. be selected.  Either deselect the chosen button within this chain or
  1174. do them all at the end.
  1175.  
  1176.    There is one common use of radio buttons in which you may short-cut
  1177. this procedure.  If the buttons each represent one possible value of
  1178. a numeric variable, for instance, a set of selector buttons
  1179. representing  colors from zero to seven, then you can compute the
  1180. initial object directly.
  1181.  
  1182.    In order for this technique to work, you must use a special
  1183. capability of the RCS.  Insert the object corresponding to a zero
  1184. value at the top (or left) of your array of buttons, then put the
  1185. "one" button below (or right) of it, and so on.
  1186.  
  1187.    When the buttons are complete,  the SORT operation is used to
  1188. guarantee that the top/left object is in fact the first child of the
  1189. parent box with the others following in order.  Due to the details of
  1190. object tree structure (to be discussed in the next column), this will
  1191. guarantee that these objects are contiguous in the resource.
  1192.  
  1193.    If you assign a name (say BUTTON1) to the first button,  then you can
  1194. initialize the correct button with the call:
  1195.  
  1196. \begin{verbatim}
  1197.    sel_obj(tree, BUTTON1 + field);
  1198. \end{verbatim}
  1199.  
  1200. where field is the variable of interest.
  1201.  
  1202.    When the dialog is complete, you can scan the radio buttons to
  1203. compute the new value for the underlying variable.  The \verb"encode()"
  1204. procedure in the listing will do this.  As always, remember to
  1205. deselect the buttons at the end.
  1206.  
  1207.    You can use offsets or multipliers if your variable's values don't
  1208. start with zero or increment by one.  If the values are irregular you
  1209. may be able to use a lookup table, at the cost of additional code.
  1210.  
  1211.    Next, I will discuss the internal structure of object
  1212. trees.  Then we'll use that knowledge to build a piece of code which
  1213. will "walk" an entire tree and apply a function to each object.
  1214. We'll apply this code to do all of the button deselects  with a
  1215. single call!  I'll also look at handling editable text fields and
  1216. discuss some ways to alter a dialog's appearance at run-time.
  1217.  
  1218. \newpage
  1219.  
  1220. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1221. \section{Object Trees}
  1222.  
  1223. We are about to delve into the mysteries of GEM resource structure,
  1224. and then use this knowledge to create some useful utilities for
  1225. handling dialogs.  As before, there is once again a demonstration file.
  1226. You will find it under the name {\tt GEMCL04.C}.
  1227.  
  1228.    The first and largest part of the listing contains a C image of a
  1229. sample resource file.  To create this listing, I used the GEM
  1230. Resource  Construction Set to create a dummy resource with three
  1231. dialogs including examples of all object types, then enabled the C
  1232. output option and saved  the resource.  If you have access to a copy
  1233. of RCS, I suggest that you  create your own listing in order to get a
  1234. feel for the results.  Then, using  either listing as a roadmap to
  1235. the resource, you can follow along as  we enter...
  1236.  
  1237. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1238. \subsection{A maze of twisty little passages}
  1239.  
  1240. While a GEM resource is loaded as a block of binary information, it
  1241. is actually composed of a number of different data structures.  These
  1242. structures are linked together in a rather tangled hierarchy.  Our
  1243. first job is to map this linkage system.
  1244.  
  1245.    The topmost structure in a resource file is the resource header.
  1246. This is an array of words containing the size and offset within the
  1247. resource of the other structures which follow.  This information is
  1248. used by  GEM during the resource load process, and you should never
  1249. need to access it. (The resource header does not appear in the C
  1250. output file; it is generated by the RSCREATE utility if the C file is
  1251. used to recreate the resource.)
  1252.  
  1253.    The next structure of interest is the tree index.  This is an
  1254. array of long pointers, each of which addresses the beginning of an
  1255. object tree. Again, you wouldn't normally access this structure
  1256. directly.  The GEM  \verb"rsrc_gaddr" call uses it when finding trees'
  1257. addresses.  This structure is called "rs\_trindex" in the C output.
  1258.  
  1259.    If you look at the contents of {\tt rs\_trindex}\/you will notice that the
  1260. values are integers, instead of the pointers I described.  What has
  1261. happened is that RCS has converted the pointers to indices into the
  1262. object array. (If you actually used the C file to recreate the
  1263. resource file, then the  pointers would be regenerated by RSCREATE.)
  1264.  
  1265.    Now you can follow the link from {\tt rs\_trindex}\/ to the objects stored
  1266. in {\tt rs\_object}.  Take (for instance) the second entry in {\tt rs\_trindex}\/ and
  1267. count down that many lines in {\tt rs\_object}.  The following line (object)
  1268. should start with a -1.  This indicates that it is the root object of
  1269. a tree.  The following objects down to the next root belong to that
  1270. tree. We'll pass over the details of inter-object linkage for now,
  1271. leaving it for later.
  1272.  
  1273.    There are a number of different fields in an object, but right now
  1274. we'll concentrate on two of them: \verb"OB_TYPE" and \verb"OB_SPEC".  The \verb"OB_TYPE"
  1275. is the field which contains mnemonics like \verb"G_STRING" and \verb"G_BOX"
  1276. indicating the type of the object.  The \verb"OB_SPEC" is the only field in
  1277. each object which  is a LONG - you can tell it by the L after the
  1278. number.
  1279.  
  1280.    What's in \verb"OB_SPEC" depends on the object type, so we need to talk
  1281. about what kinds of objects are available, what you might use them
  1282. for, and finally how they use the \verb"OB_SPEC" field.
  1283.  
  1284.    The box type objects are \verb"G_BOX", \verb"G_IBOX", and \verb"G_BOXCHAR".  A \verb"G_BOX" is
  1285. an opaque rectangle, with an optional border.  It's used to create a
  1286. solid patch of color or pattern on which to place other objects.  For
  1287. instance, the background of a dialog is a \verb"G_BOX".
  1288.  
  1289.    A \verb"G_IBOX" is a hollow box which has only a border.  (If the border
  1290. has no thickness, then the box is "invisible", hence the name.)  The
  1291. favorite use for IBOXes is to hold radio buttons.  There is also one
  1292. neat trick you can play with an IBOX.  If you have more than one
  1293. object (say an image and a string) which you would like to have
  1294. selected all at once, you can insert them in a dialog, then cover
  1295. them with an IBOX. Since the box is transparent, they will show
  1296. through.  If you now make the box selectable, clicking on it will
  1297. highlight the whole area at once!
  1298.  
  1299.    The \verb"G_BOXCHAR" is just like a \verb"G_BOX", except that a single character
  1300. is drawn in its center.  They are mostly used as "control points":
  1301. the \verb"FULLER", \verb"CLOSER", \verb"SIZER", and arrows in GEM windows are BOXCHARs, as
  1302. are  the components of the color selection gadgets in the RCS.
  1303.  
  1304.    The \verb"OB_SPEC" for box type objects is a packed bit array.  Its
  1305. various fields contain the background color and pattern, the border
  1306. thickness and color, and the optional character and its color.
  1307.  
  1308.    The string type objects are \verb"G_STRING", \verb"G_BUTTON", and \verb"G_TITLE".
  1309. \verb"G_STRINGs" (in addition to being a bad pun) are for setting up static
  1310. explanatory text within dialogs.  The characters are always written
  1311. in the "system font": full size, black, with no special effects.
  1312.  
  1313.    We have already discussed many of the uses of \verb"G_BUTTONs".  They add
  1314. a border around the text.  The thickness of a \verb"G_BUTTON"'s border is
  1315. determined by what flags are set for the object.  All buttons start
  1316. out with a border thickness of one pixel.  One pixel is added if the
  1317. \verb"EXIT" attribute is set, and one more is added if the \verb"DEFAULT" attribute
  1318. is set.
  1319.  
  1320.    The \verb"G_TITLE" type is a specially formatted text string used only in
  1321. the title bar of menus.  This type is needed to make sure that the
  1322. menus redraw correctly.  The Resource Construction Set automatically
  1323. handles inserting \verb"G_TITLEs", so you will seldom use them directly.
  1324.  
  1325.    In a resource, the \verb"OB_SPEC" for all string objects is a long
  1326. pointer to a null terminated ASCII string.  The string data in the C
  1327. file is shown in the BYTE array {\tt rs\_strings}.  Again you will notice
  1328. that  the \verb"OB_SPECs" in the C file have been converted to indices into
  1329. {\tt rs\_string}. To find the string which matches the object, take the
  1330. value of \verb"OB_SPEC" and count down that many lines in {\tt rs\_strings}.
  1331. The next line is the correct string.
  1332.  
  1333.    The formatted text object types are \verb"G_TEXT", \verb"G_BOXTEXT", \verb"G_FTEXT",
  1334. and \verb"G_FBOXTEXT".  \verb"G_TEXTs" are a lot like strings, except that you can
  1335. specify a color, different sizes, and a positioning rule for the
  1336. text.   Since they require more memory than \verb"G_STRINGs", \verb"G_TEXTs" should
  1337. be used  sparingly to draw attention to important information within
  1338. a dialog.   \verb"G_TEXTs" are also useful for automatic centering of dialog
  1339. text which is  changed at run-time.  I will describe this technique
  1340. in detail later on.
  1341.  
  1342.    The \verb"G_BOXTEXT" type adds a solid background and border to the
  1343. \verb"G_TEXT" type.  These objects are occasionally used in place of
  1344. \verb"G_BUTTONs" when their color will draw attention to an important
  1345. object.
  1346.  
  1347.    The \verb"G_FTEXT" object is an editable text field.  You are able to
  1348. specify a constant "template" of characters, a validation field for
  1349. those characters which are to be typed in, and an initial value for
  1350. the input characters.  You may also select color, size, and
  1351. positioning rule for \verb"G_FTEXTs".  We'll discuss text editing at length
  1352. below.
  1353.  
  1354.    The \verb"G_FBOXTEXT" object, as you might suspect, is the same as
  1355. \verb"G_FTEXT" with the addition of background and border.  This type is
  1356. seldom used: the extra appearance details distract attention from the
  1357. text being edited.
  1358.  
  1359.    The \verb"OB_SPEC" for a formatted text object is a pointer to yet
  1360. another type of structure: a \verb"TEDINFO".  In the C file, you will find
  1361. these in {\tt rs\_tedinfo}.  Take the \verb"OB_SPEC" value from each text type
  1362. object and count down that many entries in {\tt rs\_tedinfo}, finding the
  1363. matching \verb"TEDINFO" on the next line.  Each contains pointers to ASCII
  1364. strings for the template, validation, and initialization.  You can
  1365. find these strings in {\tt rs\_strings}, just as above.
  1366.  
  1367.    There are also fields for the optional background and border
  1368. details, and for the length of the template and text.  As we will see
  1369. when discussing  editing, the most important \verb"TEDINFO" fields are the
  1370. \verb"TE_PTEXT" pointer to  initialized text and the \verb"TE_TXTLEN" field which
  1371. gives its length.
  1372.  
  1373.    The \verb"G_IMAGE" object type is the only one of its kind.  A \verb"G_IMAGE" is
  1374. a monochrome bit image.  For examples, see the images within the
  1375. various GEM alert boxes.  Note that monochrome does not necessarily
  1376. mean black.  The image may be any color, but all parts of it are the
  1377. SAME color.  \verb"G_IMAGEs" are used as visual cues in dialogs.  They are
  1378. seldom used as selectable items because their entire rectangle is
  1379. inverted when they are clicked.  This effect is seldom visually
  1380. pleasing, particularly if the image is colored.
  1381.  
  1382.    \verb"G_IMAGE" objects have an \verb"OB_SPEC" which is a pointer to a further
  1383. structure type: the \verb"BITBLK".  By now, you should guess that you will
  1384. find it in the C file in the array {\tt rs\_bitblk}.  The \verb"BITBLK" contains
  1385. fields describing the height and width of the image in pixels, its
  1386. color, and it also contains a long pointer to the actual bits which
  1387. make up the image.  In the C file, the images are encoded as
  1388. hexadecimal words and stored in arrays named IMAG0, IMAG1, and so on.
  1389.  
  1390.    The last type of object is the \verb"G_ICON".  Like the \verb"G_IMAGE", the
  1391. \verb"G_ICON" is a bit image, but it adds a mask array which selects what
  1392. portions of the image will be drawn, as well as an explanatory text
  1393. field.  A \verb"G_ICON" may also specify different colors for its
  1394. "foreground" pixels (the ones that are normally black), and its
  1395. "background" pixels (which are normally white).
  1396.  
  1397.    The pictures which you see in Desktop windows are \verb"G_ICONs", and so
  1398. are the disks and trashcan on the desktop surface.  With the latter
  1399. you will notice the effects of the mask.  The desktop shows through
  1400. right up to the edge of the \verb"G_ICON", and only the icon itself (not a
  1401. rectangle) is inverted when a disk is selected.
  1402.  
  1403.    The \verb"OB_SPEC" of an icon points to another structure called an
  1404. \verb"ICONBLK".  It is shown in the C file as {\tt rs\_iconblk}.  The \verb"ICONBLK"\/
  1405. contains long pointers to its foreground bit array, to the mask bit
  1406. array, and to the ASCII string of explanatory text.  It also has the
  1407. foreground and background colors as well as the location of the text
  1408. area from the  upper left of the icon.  The most common use of
  1409. \verb"G_ICONs" and \verb"ICONBLKs"  is not in dialogs, instead they are used
  1410. frequently in trees which are build at run-time, such as Desktop
  1411. windows.  In an upcoming chapter, we will return to a discussion of
  1412. building such "on-the-fly" trees with \verb"G_ICONs".
  1413.  
  1414.    Now, let's recap the hierarchy of resource structures:  The
  1415. highest level structures are the resource header, and then the tree
  1416. index.  The tree index points to the beginning of each object tree.
  1417. The objects making up the tree are of several types, and depending on
  1418. that type, they may contain pointers to ASCII strings, or to \verb"TEDINFO",
  1419. \verb"ICONBLK", or \verb"BITBLK" structures.  \verb"TEDINFOs" contain further pointers to
  1420. strings; \verb"BITBLKs" have pointers to bit images; and \verb"ICONBLKs" have both.
  1421.  
  1422. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1423. \subsection{Putting it to work}
  1424.  
  1425.   The most common situations requiring you to
  1426. understand resource structures involve the use of text and editable
  1427. text objects in dialogs.  We'll look at two such techniques.
  1428.  
  1429.    Often an application requires two or more dialogs which are very
  1430. similar except for one or two title lines.  In this circumstance, you
  1431. can save a good deal of resource space by building only one dialog,
  1432. and changing the title at run time.
  1433.  
  1434.    It is easy to go wrong with this practice, however, because the
  1435. obvious tactic of using a \verb"G_STRING" and writing over its text at run
  1436. time can go wrong.  The first problem is that you must know in
  1437. advance the longest title to be used, and put a string that long into
  1438. the resource. If you don't you will damage other objects in the
  1439. resource as you copy in characters.  The other problem is that a
  1440. \verb"G_STRING" is always drawn at the same place in a dialog.  If the
  1441. length of the title changes from time to time, the dialog will have
  1442. an unbalanced and sloppy  appearance.
  1443.  
  1444.    A better way to do this is to exploit the \verb"G_TEXT" object type, and
  1445. the \verb"TEDINFO" structure.  The \verb"set_text()" routine in {\tt GEMCL04.C}
  1446.  shows
  1447. how.  The parameters provided are the tree address, the object
  1448. number, and the 32-bit address of the string to be substituted.  For
  1449. this to work, the object referenced should be defined as a \verb"G_TEXT"
  1450. type object.   Additionally, the Centered text type should be chosen,
  1451. and the object should have been "stretched" so that it fills the
  1452. dialog box from side to side.
  1453.  
  1454.    In the code, the first action is to get the \verb"OB_SPEC" from the
  1455. object which was referenced.  Since we know that the object is a
  1456. \verb"G_TEXT", the \verb"OB_SPEC" must point to a \verb"TEDINFO".  We need to change two
  1457. fields in the \verb"TEDINFO".  The \verb"TE_PTEXT" field is the pointer to the
  1458. actual string to be displayed; we replace it with the address of our
  1459. new string. The \verb"TE_TXTLEN" field is loaded with the new string's
  1460. length.  Since the Centered attribute was specified for the object,
  1461. changing the \verb"TE_TXTLEN" will cause the string to be correctly
  1462. positioned in the middle of the dialog!
  1463.  
  1464.    Editing text also requires working with the \verb"TEDINFO" structure. One
  1465. way of doing this is shown in the example.  The object to be used
  1466. (EDITOBJ) is assumed to be a \verb"G_FTEXT" or \verb"G_FBOXTEXT".  Since we will
  1467. replace the initialized text at run time, that field may be left
  1468. empty when building the object in the RCS.
  1469.  
  1470.    The basic trick of this code is to point the \verb"TEDINFO"'s \verb"TE_PTEXT" at
  1471. a string which is defined in your code's local stack.  The advantages
  1472. of this technique are that you save resource space, save static data
  1473. by putting the string in reusable stack memory, and automatically
  1474. create a scratch string which may be discarded if the dialog is
  1475. cancelled.
  1476.  
  1477.    The text string shown is arbitrarily 41 characters long.  You
  1478. should give yours a length equal to the number of blanks in the
  1479. object's template field plus one.  Note that the code is shown as a
  1480. segment,  rather than a subroutine.  This is required because the
  1481. text string must be allocated within the context of dialog handling
  1482. routine itself,  rather than a routine which it calls!
  1483.  
  1484.    After the tree address is found, the code proceeds to find the
  1485. \verb"TEDINFO" and modify its \verb"TE_PTEXT" as described above.  However, the
  1486. length which is inserted into \verb"TE_TXTLEN" must be the maximum string
  1487. length,  including the null!
  1488.  
  1489.    The final line of code inserts a null into the first character of
  1490. the uninitialized string.  This will produce an empty editing field
  1491. when the dialog is displayed.  If there is an existing value for  the
  1492. object, you should instead use \verb"strcpy()" to move it into \verb"text[]". Once
  1493. the dialog is complete, you should check its final status as
  1494. described in the last section. If an "OK" button was clicked, you
  1495. will then use \verb"strcpy()" to move the value in \verb"text[]" back to its static
  1496. location.
  1497.  
  1498.    Although I prefer this method of handling editable text, another
  1499. method deserves mention also.  This procedure allocates a full length
  1500. text string of blanks when creating the editable object in the RCS.
  1501. At  run-time, the \verb"TE_PTEXT" link is followed to find this string's
  1502. location in  the resource, and any pre-existing value is copied in.
  1503. After the dialog is run, the resulting value is copied back out if
  1504. the dialog completed successfully.
  1505.  
  1506.    Note that in both editing techniques a copy of the current string
  1507. value is kept within the application's data area.  Threading the
  1508. resource whenever you need to check a string's value is extremely
  1509. wasteful.
  1510.  
  1511.    The validation string normally contains the same character repeated
  1512. a great many times. Fortunately that is not necessary. AES duplicates
  1513. the last character of the string as often as it is needed.
  1514.  
  1515.    All masks except 'X', 'a' and 'n' convert valid characters to
  1516. uppercase. Unfortunately foreign characters are not converted when using
  1517. the 'f' or 'F' masks.
  1518.  
  1519. \begin{description}
  1520. \item[X] all characters
  1521. \item[x] all characters are converted to uppercase
  1522. \item[9] 0..9
  1523. \item[A] A..Z, foreign characters
  1524. \item[a] a..z A..Z foreign characters
  1525. \item[N] A..Z 0..9
  1526. \item[n] a..z 0..9 A..z foreign characters
  1527. \item[P] 0..9 A..Z foreign characters \verb"\ ? * : . _" 
  1528. \item[p] 0..9 A..Z foreign characters \verb"\ : . _"
  1529. \item[F] a..z 0..9 A..Z foreign characters \verb": ? * _" (no '.' but ':')
  1530. \item[f] a..z 0..9 A..Z foreign characters \verb"_" (no '.')
  1531. \end{description}
  1532.  
  1533.    One final note on editable text objects:  GEM's editor uses the
  1534. commercial at sign '\verb"@"' as a "meta-character".  If it is the first
  1535. byte of the initialized text, then the field is displayed blank no
  1536. matter what follows.  This can be useful, but is sometimes confusing
  1537. when a user in all innocence enters an \verb"@" and has his text disappear
  1538. the next time the dialog is drawn!
  1539.  
  1540.  
  1541. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1542. \subsection{Back to an omission}
  1543.  
  1544.      So, we established that resources trees are
  1545. pointed to by the tree index, and that they are composed of objects
  1546. which contain pointers onward to other structures.  However, we
  1547. passed over the issue of linkage among the objects within a tree.  It
  1548. is now time to go back and cure this omission.
  1549.  
  1550.      The technical term for the linkage scheme of an object tree is a
  1551. "right-threaded binary tree".   If you already know what this is, you
  1552. can skim over the next few paragraphs.  If you happen to have access
  1553. to a copy of the book "FUNDAMENTAL ALGORITHMS", which is part of the
  1554. series THE ART OF COMPUTER PROGRAMMING by Donald E. Knuth, you might
  1555. want to read his excellent discussion of binary trees beginning on
  1556. page 332.
  1557.  
  1558.      For the following discussion, you should have a listing of the C
  1559. image of a resource tree in front of you.  Before we begin, I should warn you of one
  1560. peculiarity of "computer trees":  They grow upside-down!  That is,
  1561. when they are diagrammed or described, their root is at the top, and
  1562. the  "leaves" grow downward.  You will see this both in the listing,
  1563. and in the way the following discussion talks about moving through
  1564. trees.
  1565.  
  1566.      Each GEM object tree begins at its ROOT object, numbered zero,
  1567. which is the object pointed at by the tree index.  There are three
  1568. link  fields at the beginning of each object.  They are called
  1569. \verb"OB_NEXT", \verb"OB_HEAD",  and \verb"OB_TAIL", which is the order in which they
  1570. appear.
  1571.  
  1572.      Each of the links is shown as an index relative to the root of
  1573. the current tree.  This means that the link '0' would refer to the
  1574. root of the tree, while '2' would indicate the object two lines below
  1575. it. The special link -1 is called NIL, and means that there is no
  1576. link in  the given direction.
  1577.  
  1578.      Each object, or node, in a tree may have "offspring" or nodes
  1579. which are nested below it.  If it does, then its \verb"OB_HEAD" will point
  1580. to its first (or "leftmost") "child", while the \verb"OB_TAIL" will point to
  1581. the last ("rightmost") of its offspring.  The \verb"OB_NEXT" pointer links
  1582. the  children together, with the \verb"OB_NEXT" of the first pointing to the
  1583. second, and so on, until the \verb"OB_NEXT" of the last finally points back
  1584. to its parent, the object at which we started.
  1585.  
  1586.      Remember that each of these children may in turn have offspring
  1587. of their own, so that the original "parent" may have a large and
  1588. complex collection of "descendents".
  1589.  
  1590.      Let's look at the first tree in the listing to see an example
  1591. of this structure.  The very first object is the ROOT.  Note that its
  1592. \verb"OB_NEXT" is NIL, meaning that there are no more objects in the tree:
  1593. the ROOT is both the beginning and the end of the tree.  In this
  1594. case, the \verb"OB_HEAD" is 1 and the \verb"OB_TAIL" is 3, showing that there are
  1595. at least two different children.
  1596.  
  1597.      Following \verb"OB_HEAD" down to the next line, we can trace through
  1598. the \verb"OB_NEXT" links (2, 3, 0) as they lead through a total of three
  1599. children and back to the ROOT.  You will notice that the first two
  1600. children have NIL for the \verb"OB_HEAD" and \verb"OB_TAILs", indicating that they
  1601. have no further offspring.
  1602.  
  1603.      However, node three, the last child of the ROOT, does have the
  1604. value 4 for both its \verb"OB_HEAD" and \verb"OB_TAIL".  By this we can tell that
  1605. it  has one, and only one, offspring.  Sure enough, when we look at
  1606. node four, we see that its \verb"OB_NEXT" leads immediately back to node
  1607. three. Additionally, it has no further offspring because its \verb"OB_HEAD"
  1608. and \verb"OB_TAIL" are NIL.
  1609.  
  1610.      You will find that object trees are always written out by the
  1611. Resource Construction Set in "pre-order".  (Again, see Knuth if you
  1612. have a copy.)  This means that the ROOT is always written first, then
  1613. its offspring left to right.  This rule is applied recursively, that
  1614. is, we go down to the next level and write out each of these nodes,
  1615. then THEIR children left to right, and so on.
  1616.  
  1617.      For a further example, look at the next tree in \verb"rs_object" in the
  1618. listing.  You will see that the ROOT has an \verb"OB_HEAD" of 1 and an
  1619. \verb"OB_TAIL" of 6, but that it actually has only three offspring (nodes 1,
  1620. 2 and 6).  We see that node 2 itself had children, and applying the
  1621. rule given above, they were written out before continuing with the
  1622. next child of the ROOT.
  1623.  
  1624.      Why was this seemingly complex structure chosen for GEM?  The
  1625. reason has do with the tasks of drawing objects in their proper
  1626. locations on the screen, and determining which object was "hit" when
  1627. a mouse click is detected.
  1628.  
  1629.      To find out how this works, we must look at four more fields
  1630. found in each object: \verb"OB_X", \verb"OB_Y", \verb"OB_WIDTH", and \verb"OB_HEIGHT".  These
  1631. fields are the last four on each line in the sample trees.
  1632.  
  1633.      Each object in a tree "owns" a rectangle on the screen.  These
  1634. fields define that rectangle.  When a resource is stored "outside"
  1635. the  program the fields are in character units, so that an object
  1636. with \verb"OB_WIDTH"  of 10 and \verb"OB_HEIGHT" of 2 (for instance) would define a
  1637. screen area 10  characters wide and 2 high.
  1638.  
  1639.      When the resource is read into memory with an \verb"rsrc_load" call,
  1640. GEM multiplies the appropriate character dimension in pixels into
  1641. each of these fields.  In this way portability is achieved: the same
  1642. resource file works for any of the ST's three resolutions.  Knowing
  1643. how \verb"rsrc_load" works, your code should treat these fields as pixel
  1644. coordinates.
  1645.  
  1646.      (I have committed one oversimplification above.  If an object is
  1647. not created on a character boundary in the RCS, then the external
  1648. storage method described will not work.  In this case, the lower byte
  1649. of each rectangle field is used to store the nearest character
  1650. position, while the upper byte stores the pixel remainder to be added
  1651. after the character size is multiplied in.
  1652.  
  1653.      Non-character-boundary objects may only be created in the "FREE"
  1654. tree mode of the Resource Construction Set (also called "PANEL" in
  1655. RCS 2.0). You should use them only in programs which will run in a
  1656. single ST screen  mode, because pixel coordinates are not portable
  1657. between resolutions.
  1658.  
  1659.      There is a bug in AES that may cause some problems: when \verb"rsrc_load"
  1660. or \verb"rsrc_obfix" convert from pixel to character coordinates, they
  1661. check for an \verb"OB_WIDTH" value of 80 characters and set the pixelwidth
  1662. to the screenwidth. On a monitor that can display more than 80 characters
  1663. in a row, an object of 80 characters can actually be larger than an object
  1664. of 90 characters! That's because if no value of 80 is found, AES multiplies
  1665. the value with the character size. Then the pixel offset from the high byte
  1666. is added.)
  1667.  
  1668.      The first real secret of object rectangles is that each \verb"OB_X" and
  1669. \verb"OB_Y" is specified RELATIVE to the X and Y coordinate of its parent
  1670. object  within the tree.  This is the first property we have seen
  1671. that is actually "inherited" from level to level within the tree.
  1672.  
  1673.      The second secret is more subtle:  Every object's rectangle must
  1674. be entirely contained within the rectangle of its parent.  This
  1675. principle goes by the names "bounding rectangles" or "visual
  1676. hierarchy".  We'll see in a moment how useful it is when detecting
  1677. mouse/object collisions.
  1678.  
  1679. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1680. \subsection{How GEM does it}
  1681.  
  1682.      Knowing these secrets, and the linkage structure  of object
  1683. trees, we can deduce how a number of the GEM operations must work.
  1684. For instance, consider \verb"objc_offset",  which returns the actual screen
  1685. X and Y  of an object.  We can see now that simply loading the \verb"OB_X"
  1686. and \verb"OB_Y" fields of  the object does not suffice: they only give the
  1687. offset relative to the parent  object.  So, \verb"objc_offset" must BEGIN
  1688. with these values, and then work its way  back up to the ROOT of the
  1689. tree, adding in the offsets found at each level.
  1690.  
  1691.      This can be done by following the \verb"OB_NEXT" links from the chosen
  1692. object.  Whenever \verb"OB_NEXT" points to an object whose \verb"OB_TAIL" points
  1693. right back  to the same location, then the new node is another level,
  1694. or "parent" in the  tree, and \verb"objc_offset" adds its \verb"OB_X" and \verb"OB_Y" into
  1695. the running totals.  When \verb"OB_NEXT" becomes NIL, then the ROOT has been
  1696. reached and the totals are the values to return.  (By the way,
  1697. remember that the \verb"OB_X" and \verb"OB_Y" of the ROOT are undefined until
  1698. \verb"form_center" has been called for the tree.  They are shown as zeroes
  1699. in the sample trees.)
  1700.  
  1701.      We can also figure out \verb"objc_draw".  It works its way DOWN the
  1702. tree, drawing each object as it comes to it.  It, too, must keep a
  1703. running X and Y variable, adding in object offsets as it descends
  1704. tree levels (using \verb"OB_HEAD"), and subtracting them again as it returns
  1705. from each level.   Since the larger objects are nearer the ROOT, we
  1706. can now see why they are drawn first, with smaller objects drawn
  1707. later or "on top of" them.
  1708.  
  1709.      (If you write an application which needs to move portions of a
  1710. dialog or screen with respect to each other, you can take advantage
  1711. of inheritance of screen position in \verb"objc_draw".  Simply by changing
  1712. the \verb"OB_X" and/or \verb"OB_Y" of an object, you can move it and its entire
  1713. sub-tree to a new location in the dialog.  For instance, changing the
  1714. coordinates of the parent box of a set of radio buttons will cause
  1715. all of the buttons to move along with it.)
  1716.  
  1717.      \verb"Objc_draw" also gives us an example of the uses of visual
  1718. hierarchy. Recall that a clipping rectangle is specified when calling
  1719. \verb"objc_draw". At each level of the tree we know that all objects below
  1720. are contained in the screen rectangle of the current object.  If the
  1721. current rectangle falls completely outside the specified clipping
  1722. rectangle, we know  immediately that we need not draw the object, or
  1723. any of its descendents! This ability to ignore an entire subtree is
  1724. called "trivial rejection".
  1725.  
  1726.      Now it's rather easy to figure out \verb"objc_find".  It starts out by
  1727. setting its "object found" variable to NIL.  It begins a "walk"
  1728. through the entire object tree, following \verb"OB_HEAD" and \verb"OB_NEXT" links,
  1729. and keeping  a current X and Y, just like \verb"objc_draw".
  1730.  
  1731.      At each node visited, it simply checks to see if the "mouse" X,Y
  1732. specified in the call are inside the current object's rectangle.  If
  1733. they  are, that object becomes the found object, and the tree walk
  1734. continues with the object's offspring, and then siblings.  Notice how
  1735. this checking of offspring makes sure that a smaller object nested
  1736. within, i.e., below, a larger object is found correctly.
  1737.  
  1738.      If the mouse X,Y position is not within the object being
  1739. checked, then by visual hierarchy it cannot be within any of its
  1740. offspring, either.   Trivial rejection wins again, and the entire
  1741. sub-tree is skipped!  \verb"Objc_find"  moves on to the \verb"OB_NEXT" of the
  1742. rejected object.
  1743.  
  1744. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1745. \subsection{Thought Experiments}
  1746.  
  1747.      Thinking about the \verb"objc_find" algorithm  reveals some information
  1748. about its performance, and a few tricks we may  use in improving the
  1749. appearance of dialogs and other object trees.
  1750.  
  1751.      First consider the problem of a dialog which contains many
  1752. objects. If we lay them all out "side-by-side", then they will all be
  1753. immediate offspring of the ROOT object.  In this situation, the
  1754. trivial rejection method will gain nothing.  The time \verb"objc_find" takes
  1755. to complete will vary linearly with the total number of objects.
  1756. This is called an "Order N" process.
  1757.  
  1758.      Suppose that instead we broke up the dialog into two areas with
  1759. invisible boxes, then broke up each of these areas in a like fashion,
  1760. and so on until we got down to the size of the individual selectable
  1761. objects.  The number of bottom level objects in this scheme is a
  1762. power  of two equal to the depth of the tree. Trivial rejection is
  1763. used to its  fullest in this case.  It is called an "Order Log N"
  1764. process, and is much  more efficient for large numbers of objects.
  1765.  
  1766.      In practice, the speed of the ST will allow you to ignore this
  1767. distinction for most dialogs and other trees.  But if you get into a
  1768. situation when speed is critical in searching a large tree, remember
  1769. that nesting objects can improve performance dramatically.
  1770.  
  1771.      If you have been following closely, you may have also noticed a
  1772. hole in the visual hierarchy rule.  It says that all of a node's
  1773. children must lie within its rectangle, but it does NOT guarantee
  1774. that the children's  rectangles will be disjoint, that is, not
  1775. overlap one another.  This peculiarity is the basis of several useful
  1776. tricks.
  1777.  
  1778.      First, remember that \verb"objc_find" always tries to scan the entire
  1779. tree.  That is, it doesn't quit when it finds the first object on the
  1780. given coordinates.  As mentioned above, this normally guarantees that
  1781. nested objects will be found.  Consider, however, what happens when
  1782. the mouse  coordinates are on a point where two or more objects {\em at
  1783. the same level }\/ overlap: they will replace one another as the "found
  1784. object" until  \verb"objc_find" returns with the one which is "last", that
  1785. is, rightmost in  the tree.
  1786.  
  1787.      This quirk can be used to advantage in a number of cases.
  1788. Suppose that you have in a dialog an image and a string which you
  1789. would  like to be selected together when either is clicked.  Nesting
  1790. within a common parent achieves nothing in this case.  Instead,
  1791. knowing that  \verb"form_do" must use \verb"objc_find", you could use our trick.
  1792.  
  1793.      You have to know that the Resource Construction Set normally
  1794. adds  objects in a tree left to right, in the order in which you
  1795. inserted them.  You proceed to build the dialog in the following
  1796. order: insert the image  first, the string next, then carefully add
  1797. an invisible box which is not  nested within either, and size it to
  1798. cover them both.  Set the \verb"SELECTABLE" attribute for the box, and the
  1799. dialog manager will find it, and invert  the whole area, when either
  1800. the image or string is clicked.
  1801.  
  1802.      By the way, remember that the SORT option in the RCS will change
  1803. the order of an object's offspring.  If you are going to try this
  1804. trick, don't use SORT!  It will undo all of your careful work.
  1805.  
  1806. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1807. \subsection{A treewalker of our own}
  1808.  
  1809.      Since the GEM system gets so much mileage  out of walking object
  1810. trees, it seems reasonable that the same method should  be useful in
  1811. application programs.  In the {\tt GEMCL05.C} you will find \verb"map_tree()". As
  1812. many LISP veterans might guess from the name, this code will traverse
  1813. all or part of an object tree, applying a function to each node.  It
  1814. also allows the function to return a true/false value specifying
  1815. whether  the sub-tree below a particular node should be ignored.
  1816. Let's examine \verb"map_tree()" in more detail as a final review of object
  1817. tree structure.
  1818.  
  1819.      First, look at the parameters.  "tree" is the long address of
  1820. the object tree of interest, as retrieved by \verb"rsrc_gaddr".  "this" is
  1821. the node at which to begin the traverse, and "last" is the node at
  1822. which to terminate.
  1823.  
  1824.      In most cases, the beginning node will be ROOT, and the final
  1825. value will be NIL.  This will result in the entire tree being
  1826. traversed. You may use other values, but be sure that you CAN get to
  1827. "last" from "this" by following tree links!  Although \verb"map_tree()"
  1828. includes a safety  check to prevent "running off" the tree, you could
  1829. get some very strange  results from incorrect parameters.
  1830.  
  1831.      The declaration for the final parameter, "routine", makes use of
  1832. C construct which may be new to some.  It is a pointer to a
  1833. subroutine which returns a WORD as a result.
  1834.  
  1835.      \verb"Map_tree()" begins by initializing a temporary variable, {\tt tmp1},
  1836. which is used to store the number of the last node visited.  Since no
  1837. node will follow itself, setting {\tt tmp1}\/ to the starting node is safe.
  1838.  
  1839.      The main loop of the routine simply repeats visiting a new node
  1840. until the last value is reached, or the safety check for end of tree
  1841. is satisfied.
  1842.  
  1843.      At any node visited, we can be in one of two conditions. Either
  1844. we are at a node which is "new", that is, not previously visited, or
  1845. else we are returning to a parent node which has already been
  1846. processed. We can detect the latter condition by comparing the last
  1847. node visited (tmp1) with the \verb"OB_TAIL" pointer of the current node.  If
  1848. the node is "old", it is not processed a second time, we simply
  1849. update tmp1 and  continue.
  1850.  
  1851.      If the node is new, we call "routine" to process it, sending the
  1852. tree address and object number as parameters.  If a FALSE is
  1853. returned,  we will ignore any subtree below this node.  On a TRUE
  1854. return, we load up  the \verb"OB_HEAD" pointer and follow it if a subtree
  1855. exists.  (If you don't care  about rejecting subtrees, simply remove
  1856. the if condition.)  Finally, if  the new node had no subtree, or was
  1857. rejected by "routine", we follow along  its \verb"OB_NEXT" link to the next
  1858. node.
  1859.  
  1860.      A simple application of our new tool shows its power. 
  1861. You may recall the tedium of deselecting every button
  1862. inside a dialog after it was completed.  Using \verb"map_tree()", you can
  1863. deselect EVERY OBJECT in the tree by using:
  1864.  
  1865. \verb"map_tree(tree, ROOT, NIL, desel_obj);"
  1866.  
  1867. You must use a slightly modified version of \verb"desel_obj()"
  1868. which always returns TRUE.  Be sure to
  1869. define or declare \verb"desel_obj()" in your code BEFORE making the \verb"map_tree"
  1870. call!
  1871.  
  1872.      In the next chapters, I will return to \verb"map_tree()" and show how it
  1873. can be used for advanced techniques such as animated dialogs.
  1874.  
  1875. \newpage
  1876.  
  1877. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1878. \section{Raster operations}
  1879.  
  1880.     This chapter of  ST Professional GEM is devoted to
  1881. explaining the raster, or "bit-blit" portion of the Atari ST's VDI
  1882. functions.
  1883.  
  1884.      Please note that this is NOT an attempt to show how to write
  1885. directly to the video memory, although you will be able to deduce a
  1886. great deal from the discussion. As usual, there is a listing to demonstrate
  1887. the topics discussed under the name of {\tt GEMCL06.C}.
  1888.  
  1889. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1890. \subsection{Defining terms}
  1891.  
  1892.      To understand VDI raster operations, you need  to understand the
  1893. jargon used to describe them.  (Many programmers will be tempted to
  1894. skip this section and go directly to the code.  Please don't do it
  1895. this time:  Learning the jargon is the larger half of understanding
  1896. the raster operations!)
  1897.  
  1898.      In VDI terms a {\tt raster area}\/ is simply a chunk of contiguous words
  1899. of memory, defining a bit image.  This chunk is called a "form".  A
  1900. form  may reside in the ST's video map area or it may be in the data
  1901. area of  your application.  Forms are roughly analogous to "blits" or
  1902. "sprites"  on other systems.  (Note, however, that there is no sprite
  1903. hardware on the ST.)
  1904.  
  1905.      Unlike other systems, there is NO predefined organization of the
  1906. raster form.  Instead, you determine the internal layout of the form
  1907. with an auxiliary data structure called the \verb"MFDB", or Memory Form
  1908. Definition Block.  Before going into the details of the \verb"MFDB", we need
  1909. to look at the various format options.  Their distinguishing features
  1910. are monochrome vs.~color, standard vs.~device-specific and even-word
  1911. vs.~fringed.
  1912.  
  1913. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1914. \subsection{Monochrome vs.~Color}
  1915.  
  1916.      Although these terms are standard, it might be better to say
  1917. "single-color vs.~multi-color".  What we are actually defining is the
  1918. number of bits which correspond to each dot, or pixel, on the screen.
  1919. In the ST, there are three possible answers. The high-resolution mode
  1920. has one bit per pixel, because there is only one "color": white.
  1921.  
  1922.      In the medium resolution color mode, there are four possible
  1923. colors for each pixel.  Therefore, it takes two bits to represent
  1924. each dot on the screen.  (The actual colors which appear are
  1925. determined by  the settings of the ST's pallette registers.)
  1926.  
  1927.      In the low resolution color mode, sixteen colors are generated,
  1928. requiring four bits per pixel.  Notice that as the number of bits per
  1929. pixel has been doubled for each mode, so the number of pixels on the
  1930. screen has been halved: 640 by 400 for monochrome, 640 by 200 for
  1931. medium-res, and 320 by 200 by low-res.  In this way the ST always
  1932. uses  the same amount of video RAM: 32K.
  1933.  
  1934.      Now we have determined how many bits are needed for each pixel,
  1935. but not how they are laid out within the form.  To find this out, we
  1936. have  to see whether the form is device-dependent or not.
  1937.  
  1938. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1939. \subsection{Standard vs.~Device-Specific Format}
  1940.  
  1941.      The standard raster form format is a constant layout which is
  1942. the same for all GEM systems.  A device-specific form is one which is
  1943. stored in the internal format of a particular GEM system.  Just as
  1944. the ST has three different screen modes, so it has three different
  1945. device-specific form formats.  We will look at standard form first,
  1946. then the ST-specific forms.
  1947.  
  1948.      First, it's reasonable to ask why a standard format is used. Its
  1949. main function is to establish a portability method between various
  1950. GEM systems.  For instance, an icon created in standard format on an
  1951. IBM PC GEM setup can be moved to the ST, or a GEM Paint picture from
  1952. an AT\&T 6300 could be loaded into the ST version of Paint.
  1953.  
  1954.      The standard format has some uses even if you only work with the
  1955. ST, because it gives a method of moving your application's icons and
  1956. images amongst the three different screen modes.  To be sure,  there
  1957. are limits to this.  Since there are different numbers of pixels  in
  1958. the different modes, an icon built in the high-resolution mode will
  1959. appear twice as large in low-res mode, and would appear oblong in
  1960. medium-res.  (You can see this effect in the ST Desktop's icons.)
  1961. Also,  colors defined in the lower resolutions will be useless in
  1962. monochrome.
  1963.  
  1964.      The standard monochrome format uses a one-bit to represent
  1965. black, and uses a zero for white.  It is assumed that the form begins
  1966. at the  upper left of the raster area, and is written a word at a
  1967. time left to right on each row, with the rows being output top to
  1968. bottom.  Within each word, the most significant bit is the left-most
  1969. on the screen.
  1970.  
  1971.      The standard color form uses a storage method called "color
  1972. planes". The high-order bits for all of the pixels are stored just as
  1973. for monochrome, followed by the next-lowest bit in another contiguous
  1974. block, and so on until all of the necessary color bits have been
  1975. stored.
  1976.  
  1977.      For example, on a 16-color system, there would be four different
  1978. planes.  The color of the upper-leftmost bit in the form would be
  1979. determined by concatenating the high-order bit in the first word of
  1980. each plane of the form.
  1981.  
  1982.      The system dependent form for the ST's monochrome mode is very
  1983. simple: it is identical to the standard form!  This occurs because
  1984. the  ST uses a "reverse-video" setup in monochrome mode, with the
  1985. background  set to white.
  1986.  
  1987.      The video organization of the ST's color modes is more
  1988. complicated. It uses an "interleaved plane" system to store the bits
  1989. which make up a pixel.  In the low-resolution mode, every four words
  1990. define the values of 16 pixels.  The high-order bits of the four
  1991. words are merged to form the left-most pixel, followed by the next
  1992. lower bit of each word, and so on.  This method is called
  1993. interleaving because the usually separate color planes described
  1994. above have been shuffled together in memory.
  1995.  
  1996.      The organization of the ST's medium-resolution mode is similar
  1997. to low-res, except the only two words are taken at a time.  These are
  1998. merged to create the two bits needed to address four colors.
  1999.  
  2000.      You should note that the actual color produced by a particular
  2001. pixel value is NOT fixed.  The ST uses a color remapping system
  2002. called a palette.  The pixel value in memory is used to address a
  2003. hardware  register in the palette which contains the actual RGB
  2004. levels to be sent to the display.  Programs may set the palette
  2005. registers with  BIOS calls, or the user may alter its settings with
  2006. the Control Panel desk accessory.  Generally, palette zero
  2007. (background) is left as white, and the highest numbered palette is
  2008. black.
  2009.  
  2010. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2011. \subsection{Even-Word vs.~Fringes}
  2012.  
  2013.      A form always begins on a word boundary, and is always stored
  2014. with an integral number of words per row.  However,  it is possible
  2015. to use only a portion of the final word.  This partial word is called
  2016. a "fringe".  If, for instance, you had a form 40 pixels wide,  it
  2017. would be stored with four words per row: three whole words, and one
  2018. word with the eight pixel fringe in its upper byte.
  2019.  
  2020. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2021. \subsection{MFDBs}
  2022.  
  2023.      Now we can intelligently define the elements of the \verb"MFDB".  Its
  2024. exact C structure definition will be found in the listing. The
  2025. {\tt fd\_nplanes}\/ entry determines the color scheme: a value of one is
  2026. monochrome, more than one denotes a color form.  If {\tt fd\_stand} is zero,
  2027. then the form is device-specific, otherwise it is in standard format.
  2028.  
  2029.      The {\tt fd\_w}\/ and {\tt fd\_h}\/ fields contain the pixel width and height of
  2030. the form respectively.  {\tt fd\_wdwidth}\/ is the width of a row in words.
  2031. If {\tt fd\_w}\/ is not exactly equal to sixteen times {\tt fd\_wdwidth}, then the
  2032. form has a fringe.
  2033.  
  2034.      Finally, {\tt fd\_addr}\/ is the 32-bit memory address of the form
  2035. itself. Zero is a special value for {\tt fd\_addr}.  It denotes that this
  2036. \verb"MFDB" is for the video memory itself.  In this case, the VDI
  2037. substitutes the actual address of the screen, and it ignores ALL of
  2038. the other parameters. They are replaced with the size of the whole
  2039. screen and number of planes in the current mode, and the form is (of
  2040. course) in device-specific format.
  2041.  
  2042.      This implies that any \verb"MFDB" which points at the screen can only
  2043. address the entire screen.  This is not a problem, however, since the
  2044. the VDI raster calls allow you to select a rectangular region within
  2045. the form.  (A note to advanced programmers:  If this situation is
  2046. annoying, you can retrieve the address of the ST's video area from
  2047. low memory, add an appropriate offset, and substitute it into the
  2048. \verb"MFDB" yourself to address a portion of the screen.)
  2049.  
  2050. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2051. \subsection{Let's operate}
  2052.  
  2053.      Now we can look at the VDI raster operations themselves.  There
  2054. are actually three: transform form, copy raster opaque, and copy
  2055. raster transparent.  Both copy raster functions can perform a variety
  2056. of logic operatoins during the copy.
  2057.  
  2058. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2059. \subsubsection{Transform Form}
  2060.  
  2061.      The purpose of this operation is to change the format of a form:
  2062. from standard to device-specific, or vice-versa.  The calling
  2063. sequence is:
  2064.  
  2065. \begin{verbatim}
  2066.      vr_trnfm(vdi_handle, source, dest);
  2067. \end{verbatim}
  2068.  
  2069. where {\tt source}\/ and {\tt dest}\/ are each pointers to \verb"MFDBs".  They ARE allowed
  2070. to be the same.  Transform form checks the {\tt fd\_stand}\/ flag in the
  2071. source \verb"MFDB", toggles it and writes it into the destination \verb"MFDB" after
  2072. rewriting the form itself.  Note that transform form CANNOT change
  2073. the number of color planes in a form: {\tt fd\_nplanes}\/ must be identical in
  2074. the two \verb"MFDBs".
  2075.  
  2076.      If you are writing an application to run on the ST only, you
  2077. will probably be able to avoid transform form entirely.  Images and
  2078. icons are stored within resources as standard forms, but since they
  2079. are monochrome, they will work "as is" with the ST.
  2080.  
  2081.      If you may want to move your program or picture files to another
  2082. GEM system, then you will need transform form.  Screen images can be
  2083. transformed to standard format and stored to disk.  Another system
  2084. with the same number of color planes could the read the files, and
  2085. transform the image to ITS internal format with transform form.
  2086.  
  2087.      A GEM application which will be moved to other systems needs to
  2088. contain code to transform the images and icons within its resource,
  2089. since standard and device-specific formats will not always coincide.
  2090.  
  2091.      If you are in this situation, you will find several utilities in
  2092. the listings which you can use to transform \verb"G_ICON" and \verb"G_IMAGE"
  2093. objects. There is also a routine which may be used with \verb"map_tree()"
  2094. from the  last column in order to transform all of the images and
  2095. icons in a resource tree at once.
  2096.  
  2097. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2098. \subsubsection{Copy Raster Opaque}
  2099.  
  2100.      This operation copies all or part of the source form into the
  2101. destination form.  Both the source and destination forms must be in
  2102. device-specific form.  Copy raster opaque is for moving information
  2103. between "like" forms, that is, it can copy from monochrome to
  2104. monochrome, or between color forms with the same number of planes.
  2105. The calling format is:
  2106.  
  2107. \begin{verbatim}
  2108.      vro_cpyfm(vdi_handle, mode, pxy, source, dest);
  2109. \end{verbatim}
  2110.  
  2111.   As above, the source and dest parameters are pointers to \verb"MFDBs"
  2112. (which in turn point to the actual forms).  The two \verb"MFDBs" may point
  2113. to memory areas  which overlap.  In this case, the VDI will perform
  2114. the move in a  non-destructive order.  Mode determines how the pixel
  2115. values in the source and destination areas will be combined.  I will
  2116. discuss it separately later on.
  2117.  
  2118.      The pxy parameter is a pointer to an eight-word integer array.
  2119. This array defines the area within each form which will be affected.
  2120. \verb"Pxy[0]" and \verb"pxy[1]" contain, respectively, the X and Y coordinates of
  2121. the upper left corner of the source rectangle.  These are given as
  2122. positive  pixel displacements from the upper left of the form.
  2123. \verb"Pxy[2]" and \verb"pxy[3]"  contain the X and Y displacements for the lower
  2124. right of the source rectangle.
  2125.  
  2126.      \verb"Pxy[4]" through \verb"pxy[7]" contain the destination rectangle in the
  2127. same format.  Normally, the destination and source should be the same
  2128. size.  If not, the size given for the source rules, and the whole are
  2129. is transferred beginning at the upper left given for the destination.
  2130.  
  2131.      This all sounds complex, but is quite simple in many cases.
  2132. Consider an example where you want to move a 32 by 32 pixel area
  2133. from one part of the display to another.  You would need to allocate
  2134. only one \verb"MFDB", with a zero in the {\tt fd\_addr}\/ field.  The VDI will take
  2135. care of counting color planes and so on.  The upper left raster
  2136. coordinates of the source and destination rectangles go into \verb"pxy[0]",
  2137. \verb"pxy[1]" and \verb"pxy[4]", \verb"pxy[5]" respectively.  You add 32 to each of these
  2138. values and insert the results in the corresponding lower right
  2139. entries, then make the copy call using the same \verb"MFDB" for both source
  2140. and destination.  The VDI takes care of any overlaps.
  2141.  
  2142. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2143. \subsubsection{Copy Raster Transparent}
  2144.  
  2145.      This operation is used for copying from a monochrome form to a
  2146. color form.  It is called transparent because it "writes through" to
  2147. all of the color planes.  Again, the forms need to be in
  2148. device-specific form.  The calling format is:
  2149.  
  2150. \begin{verbatim}
  2151.      vrt_cpyfm(vdi_handle, mode, pxy, source, dest, color);
  2152. \end{verbatim}
  2153.  
  2154.   All of the parameters are the same as copy opaque, except that
  2155. color has been added.  Color is a pointer to a two word integer
  2156. array. \verb"Color[0]" contains the color index which will be used when a
  2157. one appears in the source form, and \verb"color[1]" contains the index for
  2158. use when a zero occurs.
  2159.  
  2160.      Incidentally, copy transparent is used by the AES to draw
  2161. \verb"G_ICONs" and \verb"G_IMAGEs" onto the screen.  This explains why you do not
  2162. need to convert them to color forms yourself.
  2163.  
  2164.      (A note for advanced VDI programmers: The pxy parameter in both
  2165. copy opaque and transparent may be given in normalized device
  2166. coordinates (NDC) if the workstation associated with {\tt vdi\_handle}\/ was
  2167. opened for NDC work.)
  2168.  
  2169. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2170. \subsection{The Mode Parameter}
  2171.  
  2172.      The {\tt mode}\/ variable used in both of the copy functions is an
  2173. integer with a value between zero and fifteen. It is used to select
  2174. how the copy function will merge the pixel values of the source and
  2175. destination forms.  The complete table of functions is given in the
  2176. listings.  Since a number of these are of obscure or questionable
  2177. usefulness, I will only discuss the most commonly used modes.
  2178.  
  2179. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2180. \subsubsection{Replace Mode}
  2181.  
  2182.      A mode of 3 results in a straight-forward copy: every
  2183. destination pixel is replaced with the corresponding source form
  2184. value.
  2185.  
  2186. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2187. \subsubsection{Erase Mode}
  2188.  
  2189.      A mode value of 4 will erase every destination pixel which
  2190. corresponds to a one in the source form.  (This mode corresponds to
  2191. the "eraser" in a Paint program.)  A mode value of 1 will erase every
  2192. destination pixel which DOES NOT correspond to a one in the source.
  2193.  
  2194. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2195. \subsubsection{XOR Mode}
  2196.  
  2197.      A mode value of 6 will cause the destination pixel to be toggled
  2198. if the corresponding source bit is a one. This operation is
  2199. invertable, that is, executing it again will reverse the effects.
  2200. For this reason it is often used for "software sprites" which must be
  2201. shown and then removed from the screens.  There are some problems
  2202. with this in color operations, though - see below.
  2203.  
  2204. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2205. \subsubsection{Transparent Mode}
  2206.  
  2207.      Don't confuse this term with the copy  transparent function
  2208. itself.  In this case it simply means that ONLY  those destination
  2209. pixels corresponding with ones in the source form will  be modified
  2210. by the operation.  If a copy transparent is being performed, the
  2211. value of \verb"color[0]" is substituted for each one bit in the source form.
  2212. A mode value of 7 selects transparent mode.
  2213.  
  2214. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2215. \subsubsection{Reverse Transparent Mode}
  2216.  
  2217.      This is like transparent mode except that only those destination
  2218. pixels corresponding to source ZEROS are modified.  In a copy
  2219. transparent, the value of \verb"color[1]" is substituted for each zero bit.
  2220. Mode 13 selects reverse transparent.
  2221.  
  2222. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2223. \subsection{The problem of color}
  2224.  
  2225.      I have discussed the various modes as if they deal with one and
  2226. zero pixel values only.  This is exactly true when both forms are
  2227. monochrome, but is more complex when one or both are color forms.
  2228.  
  2229.      When both forms are color, indicating that a copy opaque is
  2230. being performed, then the color planes are combined bit-by-bit using
  2231. the rule for that mode.  That is, for each corresponding source and
  2232. destination pixel, the VDI extracts the top order bits and processes
  2233. them, then operates on the next lower bit, and so on, stuffing each
  2234. bit back into the destination form as the copy progresses.  For
  2235. example, an XOR operation on pixels valued 7 and 10 would result in a
  2236. pixel value of 13.
  2237.  
  2238.      In the case of a copy transparent, the situation is more
  2239. complex. The source form consists of one plane, and the destination
  2240. form has two  or more.  In order to match these up, the \verb"color[]" array
  2241. is used.  Whenever a one pixel is found, the value of \verb"color[0]" is
  2242. extracted and used in the bit-by-bit merge process described in the
  2243. last paragraph.  When a zero is found, the value of \verb"color[1]" is
  2244. merged into the destination form.
  2245.  
  2246.      As you can probably see, a raster copy using a mode which
  2247. combines the source and destination can be quite complex when color
  2248. planes are used!  The situation is compounded on the ST, since the
  2249. actual color values may be remapped by the palette at any time.   In
  2250. many cases, just using black and white in \verb"color[]" may achieve the
  2251. effects you desire.  If need to use full color, experimentation is
  2252. the  best guide to what looks good on the screen and what is garish
  2253. or  illegible.
  2254.  
  2255. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2256. \subsection{Optimizing raster operations}
  2257.  
  2258.      Because the VDI raster functions are extremely generalized, they
  2259. are also slower than hand-coded screen drivers which you might write
  2260. for your own special cases.  If you want to speed up your
  2261. application's raster operations without writing assembly language
  2262. drivers, the following hints will help you increase the VDI's
  2263. performance.
  2264.  
  2265. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2266. \subsubsection{Avoid merged copies}
  2267.  
  2268.      These are copy modes, such as XOR,  which  require that words be
  2269. read from the destination form.  This extra memory access increases
  2270. the running time by up to fifty percent.
  2271.  
  2272. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2273. \subsubsection{Move to corresponding pixels}
  2274.  
  2275.      The bit position within a word of the destination rectangle
  2276. should correspond with the bit position of the source rectangle's
  2277. left edge.  For instance, if the source's left edge is one pixel in,
  2278. then the destination's edge could be at one, seventeen, thirty-three,
  2279. and so.  Copies which do not obey this rule force the VDI to shift
  2280. each word of the form as it is moved.
  2281.  
  2282. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2283. \subsubsection{Avoid fringes}
  2284.  
  2285.      Put the left edge of the source and destination  rectangles on
  2286. an even word boundary, and make their widths even multiples  of
  2287. sixteen.  The VDI then does not have to load and modify partial words
  2288. within the destination forms.
  2289.  
  2290. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2291. \subsubsection{Use another method}
  2292.  
  2293.      Sometimes a raster operation is not the fastest way to
  2294. accomplish your task.  For instance, filling a rectangle with zeros
  2295. or ones may be accomplished by using raster copy modes zero and
  2296. fifteen, but it is faster to use the VDI \verb"v_bar" function instead.
  2297. Likewise, inverting an area on the screen may be done more quickly
  2298. with \verb"v_bar" by using BLACK in XOR mode.  Unfortunately, \verb"v_bar" cannot
  2299. affect  memory which is not in the video map, so these alternatives
  2300. do not always work.
  2301.  
  2302.  
  2303. \newpage
  2304.  
  2305. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2306. \section{Menu Structures}
  2307.  
  2308. In this chapter,
  2309. I will be discussing GEM menu structures and how to use them
  2310. in your application.  You will find the demonstration file containing
  2311. the code for this chapter in the listing {\tt GEMCL07.C}.
  2312.  
  2313. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2314. \subsection{Menu Basics}
  2315.  
  2316.   In ST GEM, the menu consists of a bar
  2317. across the top of the screen which displays several sub-menu
  2318. titles.  Touching one of the titles causes it to highlight,
  2319. and an associated "drop-down" to be drawn  directly below on
  2320. the screen.  This drop-down may be dismissed by moving  to
  2321. another title, or by clicking the mouse off of the drop-down.
  2322.  
  2323.  
  2324.     To make a selection, the mouse is moved over the
  2325. drop-down.  Each  valid selection is highlighted when the
  2326. mouse touches it.  Clicking the mouse  while over one of
  2327. these selections picks that item.  GEM then undraws the
  2328. drop-down, and sends a message to your application giving the
  2329. object number  of the title bar entry, and the object number
  2330. of the drop-down item which  were selected by the user.  The
  2331. selected title entry is left highlighted  while your code
  2332. processes the request.
  2333.  
  2334. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2335. \subsection{Menu Structures}
  2336.  
  2337.     The data structure which defines a GEM
  2338. menu is (surprise!) an object tree, just like the dialogs and
  2339. panels which we have discussed before.  However, the
  2340. operations of the GEM menu manager are quite different from
  2341. those of the form manager, so the internal design of the menu
  2342. tree has some curious constraints.
  2343.  
  2344.     The best way to understand these constraints is to look
  2345. at an  example.  The first item in the listing is the object
  2346. structure (only) of the menu tree from the GEM Doodle/Demo
  2347. sample application.
  2348.  
  2349.     The ROOT of a menu tree is sized to fit the entire
  2350. screen.  To satisfy the visual hierarchy principle the screen
  2351. is divided into two parts: \verb"THE BAR",
  2352. containing the menu titles, and \verb"THE SCREEN", while contains
  2353. the drop-downs when they are drawn.  Each of these areas is
  2354. defined by an object of the same name, which are the only two
  2355. objects linked directly below the ROOT of a menu tree.  You
  2356. will notice an important implication of this structure:  The
  2357. menu titles and their associated drop-downs are stored in
  2358. entirely different subtrees of the menu!
  2359.  
  2360.     While examining \verb"THE BAR" in the example listing, you may
  2361. notice that its \verb"OB_HEIGHT" is very large (513).  In
  2362. hexadecimal this is 0x0201.  This defines a height for \verb"THE BAR"
  2363. of one character plus two pixels used for spacing.  \verb"THE BAR"
  2364.  and its subtree are the only objects which are drawn on
  2365. the screen in the menu's quiescent state.
  2366.  
  2367.     The only offspring object of \verb"THE BAR" is \verb"THE ACTIVE".  This
  2368. object defines the part of \verb"THE BAR" which is covered by menu
  2369. titles.  The screen rectangle belonging to \verb"THE ACTIVE" is used
  2370. by the GEM screen manager when it  waits for the mouse to
  2371. enter an active menu title.  Notice that \verb"THE ACTIVE" and its
  2372. offspring also have \verb"OB_HEIGHTs" with pixel residues.
  2373.  
  2374.     The actual menu titles are linked left to right in order
  2375. below \verb"THE ACTIVE".  Their \verb"OB_Xs" and \verb"OB_WIDTHs" 
  2376. are arranged so that they  completely cover \verb"THE ACTIVE".  
  2377. Normally, the title objects are typed  \verb"G_TITLE", a special 
  2378. type which assures that the title bar margins are correctly drawn.
  2379.  
  2380.     \verb"THE SCREEN" is the parent object of the drop-down boxes
  2381. themselves. They are linked left to right in an order
  2382. identical with their titles, so  that the menu manager can
  2383. make the correct correspondence at run-time.  The \verb"OB_X" of
  2384. each drop-down is set so that it is positioned below its
  2385. title on the screen.
  2386.  
  2387.     Notice that it is safe to overlap the drop-downs within a
  2388. menu,  since only one of them will be displayed at any time.
  2389. There is one constraint on the boxes however:  They must be
  2390. no greater than a quarter screen in total size.  This is the
  2391. size of the off-screen blit buffer which is used by GEM to
  2392. store the screen contents when the drop-down is drawn.  If
  2393. you exceed this size, not all the screen under the drop-down
  2394. will be restored, or the ST may crash!
  2395.  
  2396.     The entries within a drop-down are usually \verb"G_STRINGs",
  2397. which are optimized for drawing speed.  The rectangles of
  2398. these entries must  completely cover the drop-down, or the
  2399. entire drop-down will be inverted  when the mouse touches an
  2400. uncovered area!  Techniques for using objects  other than
  2401. \verb"G_STRINGs" are discussed later on.
  2402.  
  2403.     The first title and its corresponding drop-down are
  2404. special.  The title name, by custom, is set to DESK.  The
  2405. drop-down must contain exactly  eight \verb"G_STRING" objects.  The
  2406. first (again by custom) is the INFO entry,  which usually
  2407. leads to a dialog displaying author and copyright information
  2408. for your application.  The next is a separator string of
  2409. dashes with the \verb"DISABLED" flag set.  The following six objects
  2410. are dummy strings which GEM fills in with the names of desk
  2411. accessories when your menu is loaded.
  2412.  
  2413.     The purpose of this description of menu trees is to give
  2414. you an understanding of what lies "behind the scenes" in the
  2415. next section, which describes the run-time menu library
  2416. calls.  In practice, the Resource Construction Set provides
  2417. "blank menus" which include all of the required elements, and
  2418. it also enforces the constraints on internal structure.  You
  2419. only need to worry about these if you modify the menu tree
  2420. "on-the-fly".
  2421.  
  2422. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2423. \subsection{Using the menu}
  2424.  
  2425. Once you have loaded the application's
  2426. resource, you can ask the AES to install your menu.  You must
  2427. first get the address of the menu tree within the resource
  2428. using:
  2429.  
  2430. \begin{verbatim}
  2431.     rsrc_gaddr(R_TREE, MENUTREE, &ad_menu);
  2432. \end{verbatim}
  2433.  
  2434.  assuming that \verb"MENUTREE" is the name you gave the menu in the
  2435. RCS, and that {\tt ad\_menu} is a LONG which will receive the
  2436. address.  Then you call the AES to establish the menu:
  2437.  
  2438. \begin{verbatim}
  2439.     menu_bar(ad_menu, TRUE);
  2440. \end{verbatim}
  2441.  
  2442.  At this point, the AES draws your menu bar on the screen and
  2443. animates it when the user moves the mouse into the title
  2444. area.
  2445.  
  2446.     The AES indicates that the user has made a menu selection
  2447. by sending your application a message.  The message type is
  2448. \verb"MN_SELECTED",  which will be stored in \verb"msg[0]", the first
  2449. location in the message  returned by \verb"evnt_multi()".
  2450.  
  2451.     The AES also stores the object number of the selected
  2452. menu's  title in \verb"msg[3]", and the object number of the
  2453. selected menu item in \verb"msg[4]".  Generally, your application
  2454. will process menu messages with nested C switch statements.
  2455. The outer switch will have one case for each menu title, and
  2456. the inner switch statements will have a case for each entry
  2457. within the selected menu.  (This implies that you must give a
  2458. name to each title and to each menu entry when you create the
  2459. menu in the RCS.)
  2460.  
  2461.     After the user has made a menu selection, the AES leaves
  2462. the title of the chosen menu in reverse video to indicate
  2463. that your application is busy processing the message.  When
  2464. you done with whatever action is indicated, you need to
  2465. return the title to a normal state. This is done with
  2466.  
  2467. \begin{verbatim}
  2468.     menu_tnormal(ad_menu, msg[3], TRUE);
  2469. \end{verbatim}
  2470.  
  2471.  (Remember that \verb"msg[3]" is the title's object number.)
  2472.  
  2473.     When your application is ready to terminate, it should
  2474. delete its menu bar.  Do this with the call:
  2475.  
  2476. \begin{verbatim}
  2477.     menu_bar(ad_menu, FALSE);
  2478. \end{verbatim}
  2479.  
  2480. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2481. \subsection{Getting fancy}
  2482.  
  2483.   The techniques above represent the bare
  2484. minimum to handle menus.  In most cases, however, you will
  2485. want your menus to be more "intelligent" in displaying the
  2486. user's options.  For instance, you can prevent many user
  2487. errors by disabling inappropriate choices, or you can save
  2488. space on drop-downs by showing only one line for a toggle and
  2489. altering its text or placing and removing a check mark when
  2490. the state is changed.  This section discusses these and other
  2491. advanced techniques.
  2492.  
  2493.     It is a truism of user interface design that the best way
  2494. to deal with an error is not to let it happen in the first
  2495. place.  It  many cases, you can apply this principle to GEM
  2496. menus by disabling  choices which should not be used.  If
  2497. your application uses a "selection  precedes action" type of
  2498. interface, the type of object selected may  give the
  2499. information needed to do this.   Alternately, the state of
  2500. the  underlying program may render certain menu choices
  2501. illegal.
  2502.  
  2503.     GEM provides a call to disable and re-enable menu
  2504. options. The call is:
  2505.  
  2506. \begin{verbatim}
  2507.     menu_ienable(ad_menu, ENTRY, FALSE);
  2508. \end{verbatim}
  2509.  
  2510.  to disable a selection.  The entry will be grayed out when
  2511. it is drawn, and will not invert under the mouse and will not
  2512. be selected by the user. Substituting TRUE for FALSE
  2513. re-enables the option.  \verb"ENTRY" is the name  of the object
  2514. which is being affected, as assigned in the RCS.
  2515.  
  2516.     Note that \verb"menu_ienable()" will not normally affect the
  2517. appearance or operation of menu TITLE entries.  However,
  2518. there is an undocumented feature which allows this.  If \verb"ENTRY"
  2519. is replaced by the object number of a title bar entry with
  2520. its top bit set, then the entire associated drop-down will be
  2521. disabled or re-enabled as requested, and the title's
  2522. appearance will be changed.  But, be warned that this feature
  2523. did not work reliably in some early versions of GEM.  Test it
  2524. on your copy of ST GEM, and use it with caution when you
  2525. cannot control the version under which your application may
  2526. run.
  2527.  
  2528.     It is also possible to disable menu entries by directly
  2529. altering the \verb"DISABLED" attribute within the \verb"OB_STATE" word.
  2530. The routines \verb"enab_obj()" and \verb"disab_obj()" in the listing show
  2531. how this is done.  They are also used in \verb"set_menu()", which
  2532. follows them immediately.
  2533.  
  2534.     \verb"Set_menu()" is a utility which is useful when you wish to
  2535. simultaneously enable or disable many entries in the menu
  2536. when the program's state changes or a new object is selected
  2537. by the user.   It is called with
  2538.  
  2539. \begin{verbatim}
  2540.     set_menu(ad_menu, vector);
  2541. \end{verbatim}
  2542.  
  2543.  where vector is a pointer to an array of WORDs.  The first
  2544. word of the array determines the default state of menu
  2545. entries.  If it is TRUE, then \verb"set_menu()" enables all entries
  2546. in every drop-down of the menu tree, except that the DESK
  2547. drop-down is unaffected.  If it is FALSE, then every menu
  2548. entry is disabled.
  2549.  
  2550.     The following entries in the array are the numbers of
  2551. menu entries which are to be toggled to the reverse of the
  2552. default state. This list is terminated by a zero entry.
  2553.  
  2554.     The advantage of \verb"set_menu()" is that it allows you to
  2555. build a collection of menu state arrays, and associate one
  2556. with each type of user-selected object, program state, and so
  2557. on.  Changing the status of the menu tree may then be
  2558. accomplished with a single call.
  2559.  
  2560. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2561. \subsection{Check, please?}
  2562.  
  2563. One type of state indicator which may
  2564. appear  within a drop-down is a checkmark next to an entry.
  2565. You can add the  checkmark with the call:
  2566.  
  2567. \begin{verbatim}
  2568.     menu_icheck(ad_menu, ENTRY, TRUE);
  2569. \end{verbatim}
  2570.  
  2571.  and remove it by replacing the TRUE with FALSE.  As above,
  2572. \verb"ENTRY" is the name of the menu entry of interest.  The
  2573. checkmark appears inside the left boundary of the entry
  2574. object, so leave some space for it.
  2575.  
  2576.     The \verb"menu_icheck()" call is actually changing the state of
  2577. the \verb"CHECKED" flag within the entry object's \verb"OB_STATE" word.  If
  2578. necessary, you may alter the flag directly using \verb"do_obj()" and
  2579. \verb"undo_obj()" from the example listing.
  2580.  
  2581. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2582. \subsection{Now you see it, now you don't}
  2583.  
  2584. You can also alter the
  2585. text  which appears in a particular menu entry (assuming that
  2586. the entry is  a \verb"G_STRING" object).  The call
  2587.  
  2588. \begin{verbatim}
  2589.     menu_text(ad_menu, ENTRY, ADDR(text));
  2590. \end{verbatim}
  2591.  
  2592.  will substitute the null-terminated string pointed to by
  2593. text for whatever is currently in \verb"ENTRY".  Remember to make
  2594. the drop-down wide enough to handle the largest text string
  2595. which you may substitute.  In the interests of speed,
  2596. \verb"G_STRINGs" drawn within drop-downs are not clipped, so you may
  2597. get garbage characters on the desktop if you do not size the
  2598. drop-down properly!
  2599.  
  2600.     The \verb"menu_text()" call actually alters the \verb"OB_SPEC" field of
  2601. the menu entry object to point to the string which you
  2602. specify.  Since the menu tree is a static data structure
  2603. which may be directly accessed by the AES at any time, be
  2604. sure that the string is also statically allocated and that it
  2605. is not modified without first being delinked from the menu
  2606. tree. Failure to do this may result in random crashes when
  2607. the user accesses the drop-down!
  2608.  
  2609. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2610. \subsection{Lunch and dinner menus}
  2611.  
  2612. Some applications may have such
  2613. a wide  range of operations that they need more than one menu
  2614. bar at different  times.  There is no problem with having
  2615. more than one menu tree in a  resource, but the AES can only
  2616. keep track of one at a time.  Therefore,  to switch menus you
  2617. need to use
  2618.  
  2619. \begin{verbatim}
  2620.     menu_bar(ad_menu1, FALSE);
  2621. \end{verbatim}
  2622.  
  2623. to release  the first menu, then use
  2624.  
  2625. \begin{verbatim}
  2626.     menu_bar(ad_menu2, TRUE);
  2627. \end{verbatim}
  2628.  
  2629. to load the second menu tree.
  2630.  
  2631.     Changing the entire menu is a drastic action.  Out of
  2632. consideration for your user, it should be associated with
  2633. some equally obvious change in the application which has just
  2634. been manually requested.  An example  might be changing from
  2635. spreadsheet to data graphing mode in a multi-function
  2636. program.
  2637.  
  2638. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2639. \subsection{Do it yourself}
  2640.  
  2641. In one of the next sections, I will discuss how
  2642. to set up user-defined drawing objects.  If you have already
  2643. discovered them  on your own, you can use them within a
  2644. drop-down or as a title entry.
  2645.  
  2646.     If the user-defined object is within a drop-down, its
  2647. associated drawing code will be called once when the
  2648. drop-down is first drawn. It will then be called in
  2649. "state-change" mode when the entry is highlighted (inverted).
  2650. This allows you to use non-standard methods to show
  2651. selection, such as outlines.
  2652.  
  2653.     If you try to insert a user-defined object within the
  2654. menu title area, remember that the \verb"G_TITLE" object which you
  2655. are replacing includes part of the dark margin of the bar.
  2656. You will need to experiment with your object drawing code to
  2657. replicate this effect.
  2658.  
  2659. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2660. \subsection{Make pretty}
  2661.  
  2662.   There are a number of menu formatting
  2663. conventions which have become standard practice.  Using these
  2664. gives your application a recognizable "look-and-feel" and
  2665. helps users learn it.  The following section reviews these
  2666. conventions, and supplies a few hints and tricks to obtain a
  2667. better appearance for you menus.
  2668.  
  2669.     The second drop-down is customarily used as the FILE
  2670. menu.  It  contains options related to loading and saving the
  2671. files used by the  application, as well as entries for
  2672. clearing the workspace and  terminating the program.
  2673.  
  2674.     You should avoid crowding the menu bar.  Leave a couple
  2675. of spaces between each entry, and try not to use more than
  2676. 70\% of the bar.  Not only does this look better, but you will
  2677. have space for longer words if you translate your application
  2678. to a foreign language.
  2679.  
  2680.     Similarly, avoid cluttering menu drop-downs.  Try to keep
  2681. the number of options to no more than ten unless they are
  2682. clearly related, such as colors.  Separate off dissimilar
  2683. entries with the standard disabled dashes line.  (If you are
  2684. using \verb"set_menu()", remember to consider the separators when
  2685. setting up the state vectors.)
  2686.  
  2687.     If the number of options grows beyond this bound, it may
  2688. be time to move them to a dialog box.  If so, it is a
  2689. convention to put three dots following each menu entry which
  2690. leads to a dialog. Also, allow a margin on the menu entries.
  2691. Two leading blanks and a minimum of one trailing blank is
  2692. standard, and allows room for checkmarks if they are used.
  2693.  
  2694.     Dangerous menu options should be far away from common
  2695. used entries, and are best separated with dashed lines.  Such
  2696. options should either lead to a confirming go/no-go alert, or
  2697. should have associated "undo" options.
  2698.  
  2699.     After you have finished defining a menu drop-down with
  2700. the RCS,  be sure that its entries cover the entire box.
  2701. Then use ctrl-click to  select the drop-down itself, and SORT
  2702. the entries top to bottom.  This  way the drop-down draws in
  2703. smoothly top to bottom.
  2704.  
  2705.     Finally, it is possible to put entries other than
  2706. \verb"G_STRINGs" into drop-downs.  In the RCS, you will need to
  2707. import them via the clipboard from the Dialog mode.
  2708.  
  2709.     Some non-string object, such as icons and images, will
  2710. look odd  when they are inverted under the mouse.  There is a
  2711. standard trick for  dealing with this problem.  Insert the
  2712. icon or whatever in the drop-down first.  Then get a \verb"G_IBOX"
  2713. object and position and size it so that it covers the first
  2714. object as well as the extra area you would like to be
  2715. inverted.
  2716.  
  2717.     Edit the \verb"G_IBOX" to remove its border, and assign the
  2718. entry name  to it.  Since the menu manager uses \verb"objc_find()",
  2719. it will detect and invert this second object when the mouse
  2720. moves into the drop-down. 
  2721. Finally, {\bf do not} sort a drop-down which has been set  up this
  2722. way!
  2723.  
  2724.  
  2725. \newpage
  2726.  
  2727. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2728. \section{An insider's AES tricks}
  2729.  
  2730.      This chapter of ST PRO  GEM is
  2731. devoted to exploring some of the little documented,  but powerful,
  2732. features  of GEM.   Like the authors of most complex systems,  the
  2733. GEM  programmers left behind a set of "hooks",  powerful  features
  2734. which would aid them in enhancing the system later.  I am going to
  2735. lay  out  a number of these methods which have served me  well  in
  2736. making  creative use of the AES.   You will find that most of them
  2737. concern  the object and form libraries,  since I was most involved
  2738. in those parts of GEM.  There are probably many more useful tricks
  2739. waiting  to be found in other parts of GEM,  so if you happen onto
  2740. one, please let me know in the Feedback! The listing for this
  2741. chapter is {\tt GEMCL11.C}.
  2742.  
  2743. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2744. \subsection{Powerful objects}
  2745.  
  2746.     The  first  four tricks all involve  augmenting  standard  AES
  2747. objects.   This is a powerful technique for two  reasons.   First,
  2748. you  can  take  advantage  of the  regular  AES  object  and  form
  2749. libraries  to draw and handle most of your objects,  so that  your
  2750. program need only process the exceptions.  Second, you can use the
  2751. RCS  to  copy  the  special  objects  into  multiple  dialogs   or
  2752. resources.   These  four tricks are Extended Object  Types,  User-
  2753. defined Objects,  \verb"TOUCHEXIT",  and \verb"INDIRECT".  Let's look at each of
  2754. them in turn.
  2755.  
  2756. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2757. \subsection{Extended object types}
  2758.  
  2759.     If you look at the AES Object Library documentation,  you will
  2760. notice that the values for the \verb"OB_TYPE" field in an object are  all
  2761. 32 or less.   This means that a number of bits are unused in  this
  2762. field.   In fact,  the AES completely ignores the top byte of  the
  2763. \verb"OB_TYPE" field.   In addition, the RCS ignores the top byte, but it
  2764. also  preserves  its value when an object  is  read,  written,  or
  2765. copied.
  2766.  
  2767.      This  gives  you one byte per object to use as you  see  fit.
  2768. Since  the  processing of an object or dialog is (so far)  in  the
  2769. hands of the AES,  the best uses of Extended Types are in flagging
  2770. methods for initializing an object or handling its value when  the
  2771. dialog  completes.
  2772.  
  2773.      For  example,  you  might  have  several  dialogs  containing
  2774. editable numeric fields.   The Extended Type of each numeric field
  2775. could be set to the index of the corresponding value in an  array.
  2776. Then your application's dialog initialization code could scan  the
  2777. object  tree  for  such objects,  pick up  the  appropriate  value
  2778. from the array and convert it to ASCII,  storing the result in the
  2779. resource's  string  area.   When the dialog was finished,  another
  2780. pass could be made to reconvert the ASCII to binary and store away
  2781. the results in the array.   (Note that the \verb"map_tree()" utility from
  2782. a previous chapter will scan an entire resource tree.)
  2783.  
  2784.      Another  application  is  to assign  uniform  codes  to  exit
  2785. buttons  in  dialogs.   If you give every "OK" button an  Extended
  2786. Type  of one,  and every "Cancel" button an Extended Type of  two,
  2787. then  you  needn't  worry about naming every  exit  object.   Just
  2788. examine  the Extended Type of the object returned by \verb"form_do",  and
  2789. proceed accordingly.
  2790.  
  2791.      The catch, of course, is that you have to find a way to enter
  2792. the  Extended  Type code in the first place.   Version 1.0 of  the
  2793. RCS, as shipped with the Atari developer's kit, makes no provision
  2794. for this.  So you have your choice of two methods for creating the
  2795. first  object with each Extended Type code.
  2796.  
  2797.      First,  you can dump out a C source of a resource, insert the
  2798. new type code by hand,  and regenerate the resource with \verb"STCREATE".
  2799. Alternately,  you could carefully modify the binary resource using
  2800. SID.   You will probably want to reread the AES object manual and 
  2801. use the C source as a guide when doing so.
  2802. In both cases, you should make things easy on yourself by creating
  2803. a  one  dialog resource with only a single object other  than  the
  2804. root.   Version  2.0  of  the RCS will let you directly  enter  an
  2805. Extended Type, but it has not yet been released for the ST by DRI.
  2806.  
  2807.      Once  you have created a prototype extended object by  either
  2808. method, you can use the RCS to propogate it.  The safest way is to
  2809. use the MERGE option to add the modified tree to the resource  you
  2810. are building.  Then copy the prototype object via the clipboard to
  2811. your dialog(s), deleting the extra tree when you are done.  If you
  2812. are  using several different extended objects,  you can use  MERGE
  2813. and clipboard copies to get them all into one tree which will then
  2814. become your own object library.
  2815.  
  2816.      The  second way of using RCS is easier,  but more  dangerous.
  2817. If you want to try the following technique,  BACK UP YOUR RCS DISK
  2818. FIRST!   Put  simply,  the RCS does not care what is in its dialog
  2819. partbox. It will make copies of anything that it finds there! This
  2820. gives you the option of using the RCS on ITS OWN RESOURCE in order
  2821. to add your customized objects to the partbox.
  2822.  
  2823.      To do this, open RCS.RSC from the RCS.  Since there is no DEF
  2824. file,  you will get a collection of question mark icons.   Use the
  2825. NAME option to make TREE5 into a DIALOG.    Open it,  and you will
  2826. see the dialog partbox.
  2827.  
  2828.      Now you can use the MERGE technique described above to insert
  2829. your  customized  objects.   Then SAVE the modified resource,  and
  2830. rerun the RCS.  Your new objects should now appear in the partbox.
  2831. If  you added several,  you may have to stretch the partbox to see
  2832. them  all.   You can now make copies of the new objects just  like
  2833. any other part.  (Note: DO NOT modify the alert or menu partboxes,
  2834. you will probably crash the RCS.)
  2835.  
  2836. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2837. \subsection{User-defined objects}
  2838.  
  2839.     The one type of object which was not discussed in the  earlier
  2840. chapters on  AES objects was \verb"G_USERDEF",  the  programmer  defined
  2841. object.   This  is  the  hook  for  creating  objects  with  other
  2842. appearances  beyond those provided by the standard  AES.   By  the
  2843. way, you should note that the \verb"G_PROGDEF" and \verb"APPLBLK" mnemonics used
  2844. in  the  AES documents are incorrect;  the actual  names  as  used
  2845. defined \verb"OBDEFS.H" are \verb"G_USERDEF" and \verb"USERBLK".
  2846.  
  2847.      The  RCS does not support the creation of \verb"G_USERDEF"  objects,
  2848. since  it  has  no idea how they will be drawn  by  your  program.
  2849. Instead,  you  must insert a dummy object into your resource where
  2850. you  want  the  \verb"G_USERDEF"  to appear,  and  patch  it  after  your
  2851. application performs its resource load.
  2852.  
  2853.      You   must  replace  the  object's  existing \verb"OB_TYPE" with
  2854. \verb"G_USERDEF",  though you may still use the upper byte as an Extended
  2855. Type.   You  must  also  change the \verb"OB_SPEC" field to be  a  32-bit
  2856. pointer  to  a \verb"USERBLK" structure.   An \verb"USERBLK" is simply two  LONG
  2857. (32-bit)  fields.   The  first is the address of the drawing  code
  2858. associated  with  the  user  defined object.   The  second  is  an
  2859. arbitrary 32-bit value assigned to the object by your application.
  2860.  
  2861. This one is useful if several objects have different \verb"USERBLK"s but
  2862. call the same drawing code, because the code can detect who called it
  2863. without without evaluating \verb"pb_tree" or \verb"pb_obj". When called,
  2864. AES will pass the PARMBLK structure which also contains position and size of
  2865. the object. Whenever the object needs to be redrawn the \verb"objc_draw"
  2866. or \verb"objc_change" calls in turn call \verb"ub_code" as a subroutine
  2867. of the AES. So the routine will be called in supervisor mode and all
  2868. registers except for \verb"A0-A2/D0-D2" MUST be saved. Also \verb"ub_code"
  2869. may NOT make any AES calls because GEM is not reentrant. VDI, XBIOS, BIOS
  2870. and GEMDOS routines may be called however. \verb"ub_code" will only be called
  2871. if the object lies within the clipping area. If \verb"ub_code" was called 
  2872. during an \verb"objc_change" call, the state of the object may just have
  2873. changed. Then, parameters \verb"pb_prevstate" and \verb"pb_currstate"
  2874. in the structure \verb"PARMBLK" contain different values.
  2875.  
  2876. The object's status bits will be evaluated immediately after return
  2877. of \verb"ub_code". These are not taken from the \verb"OBJECT" structure,
  2878. but are returned by \verb"ub_code"! So it's sufficient to return
  2879. \verb"pb_currstate" to make AES change the object properly.
  2880.  
  2881.      You can designate objects for conversion to \verb"G_USERDEFs" in the
  2882. normal fashion by assigning them names which are referenced one by
  2883. one in your initialization code.   You can also combine two tricks
  2884. by using the Extended Type field as a designator for objects to be
  2885. converted to \verb"G_USERDEF".  Each tree can then be scanned for objects
  2886. to  be converted.   There is a short code segment in the  listings
  2887. which demonstrates this technique.
  2888.  
  2889.      My  usual  convention  is to define new  drawing  objects  as
  2890. variants  of  existing objects,  using the Extended Type field  to
  2891. designate the particular variation.   Thus an Extended Type of one
  2892. might designate a \verb"G_BUTTON" with rounded corners,  while a value of
  2893. two  could  flag  a \verb"G_STRING" of boldface text.   When  using  this
  2894. technique,  the  RCS can be used to build a rough facsimile of the
  2895. dialog  by inserting the basic object type as  placeholders.   The
  2896. existing  \verb"OB_SPEC"  information can then be copied  to  the  second
  2897. position in the \verb"USERBLK" when the object is initialized.
  2898.  
  2899.      One final note before moving on:  There is no reason that the
  2900. \verb"USERBLK"  cannot be extended beyond two fields.   You might want to
  2901. add  extra words to store more information related to drawing  the
  2902. object, such as its original type.
  2903.  
  2904.      The  AES will call your drawing code whenever  the \verb"G_USERDEF"
  2905. needs  to be drawn.   This occurs when you make an \verb"objc_draw"  call
  2906. for its tree,  or when an \verb"objc_change" occurs for that object.   If
  2907. your user-defined object is in a menu drop-drop, then your drawing
  2908. code will be called any time the user exposes that menu.
  2909.  
  2910.      Before  getting  into the details of the AES  to  application
  2911. calling  sequence,  some  warnings are in order.   First,  remember
  2912. that your drawing code will execute in the AES' context, using its
  2913. stack.   Therefore,  be careful not to overuse the stack with deep
  2914. recursion, long parameter lists, or large dynamic arrays.  Second,
  2915. the  AES  is NOT re-entrant,  so you may not make ANY calls to  it
  2916. from within a \verb"G_USERDEF" procedure.   You may,  of course, call the
  2917. VDI.   Finally,  realize  that drawing code associated with a menu
  2918. object may be called by the AES at any time.   Exercise great care
  2919. in  sharing  data  space between such code and  the  rest  of  the
  2920. application!
  2921.  
  2922.      When your drawing code is called by the AES, the stack is set
  2923. up  as if a normal procedure call had occured.   There will be one
  2924. parameter  on the stack:  a 32-bit pointer to a \verb"PARMBLK" structure.
  2925. This structure lies in the AES' data space, so do not write beyond
  2926. its end!
  2927.  
  2928.      The  \verb"PARMBLK" contains 15 words.   The first two are the  long
  2929. address of the object tree being drawn,  and the third word is the
  2930. number of the \verb"G_USERDEF" object.   You may need these values if the
  2931. same  drawing  code is used for more than one object  at  a  time.
  2932. Words  four  and five contain the previous  and  current \verb"OB_STATE"
  2933. values of the object.  If these values are different, your drawing
  2934. code  is  being  called in response  to  an  \verb"objc_change"  request.
  2935. Otherwise, the active AES call is an \verb"objc_draw".
  2936.  
  2937.      Words six through nine contain the object's rectangle on  the
  2938. screen.   Remember  that  you cannot call \verb"objc_offset"  within  the
  2939. drawing code,  so you will need these values!  The next four words
  2940. contain the clipping rectangle specified in the active \verb"objc_change"
  2941. or \verb"objc_draw" call.   You should set the VDI clip rectangle to this
  2942. value before doing any output to the screen.
  2943.  
  2944.      The last two words in the \verb"PARMBLK" contain a copy of the extra
  2945. 32-bit parameter from the object's \verb"USERBLK".   If you have followed
  2946. the  method of copying an \verb"OB_SPEC" into this location,  these words
  2947. will be your pointer to a string, or \verb"BITBLK", or whatever.
  2948.  
  2949.      When  your drawing routine is done,  it should return a  zero
  2950. value  to  the AES.   This is a "magic" value;  anything else will
  2951. stop the drawing operation.
  2952.  
  2953.      The listing contains a sample drawing routine which  defines
  2954. one extended drawing object,  a rounded rectangle button.  You can
  2955. use  this procedure as a starting point for your own User  Defined
  2956. objects.
  2957.  
  2958. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2959. \subsection{Put anything you want on the Desktop!}
  2960.  
  2961.      In a previous chapter I described the use  of  the  \verb"WF_NEWDESK"
  2962. \verb"wind_set"  call to substitute your own object tree for  the  normal
  2963. green  desktop background.   If the tree you supply contains  User
  2964. Defined  objects,  you can draw whatever you want on the  desktop!
  2965. Some  of the things you might try are free hand drawings  imported
  2966. in  metafile  format from EasyDraw,  or whole  screen  bit  images
  2967. generated by Degas.   If you do the latter, you will have to store
  2968. the entire image off screen and blit parts of it to the display as
  2969. requested.
  2970.  
  2971.      In  any case,  remember that your desktop drawing code can be
  2972. called any time that a window is moved,  so exercise the same care
  2973. as with a menu drawer.   Also, be aware that making the \verb"WF_NEWDESK"
  2974. call  does  not force an immediate redraw of the desktop.   To  do
  2975. that, do a \verb"form_dial(3)" call for the entire desktop rectangle.
  2976.  
  2977. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2978. \subsection{The Touchexit Flag}
  2979.  
  2980.    The  \verb"TOUCHEXIT" attribute is an alternative to  the  more  usual
  2981. \verb"EXIT".   When the \verb"TOUCHEXIT" bit is set in an object's \verb"OB_FLAG" word,
  2982. the \verb"form_do" routine will exit immediately when the mouse button is
  2983. pressed  with  the  cursor  over  the  object.    Your  code   can
  2984. immediately take control of the mouse and display, without waiting
  2985. for the release of the button.  This method is used for generating
  2986. effects such as slider bars within otherwise normal dialogs.
  2987.  
  2988.      The  easiest  way to code a \verb"TOUCHEXIT" handler is to  place  a
  2989. loop  around the \verb"form_do" call.   If the object number returned  is
  2990. \verb"TOUCHEXIT",  then the animation procedure is called,  followed by a
  2991. resumption   of  the  \verb"form_do"  (WITHOUT  recalling  \verb"form_dial"   or
  2992. \verb"objc_draw"!).   If the object returned is a normal \verb"EXIT", the dialog
  2993. is  complete and control flows to the cleanup code.
  2994.  
  2995.      There is one idiosyncrasy of \verb"TOUCHEXIT" which should be noted.
  2996. When the AES "notices" that the mouse button has been pressed over
  2997. a \verb"TOUCHEXIT",  it immediately retests the button state.   If it has
  2998. already  been  released,  it  waits to see if  a  double click  is
  2999. performed.  If so, the object number returned by \verb"form_do" will have
  3000. its  high  bit set.   If you don't care about double clicks,  your
  3001. code should mask off this flag.   However, you may want to use the
  3002. double click to denote some enhanced action.  For example, the GEM
  3003. file selector uses a double click on one of the file name  objects
  3004. to indicate a selection plus immediate exit.
  3005.  
  3006. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3007. \subsection{The Indirect Flag}
  3008.  
  3009.     If the \verb"INDIRECT" bit is set in an object's \verb"OB_STATE"  word,  the
  3010. AES interprets the 32-bit \verb"OB_SPEC" field as a pointer to the memory
  3011. location  in which the {\em actual}\/ \verb"OB_SPEC" is to be found.   Like  User
  3012. Defined objects,  this capability is not supported by the RCS,  so
  3013. you  have to set up the \verb"INDIRECT" bit and alter the \verb"OB_SPEC" at  run
  3014. time.
  3015.  
  3016.      The value of \verb"INDIRECT" is that you can use it to associate  an
  3017. AES  object with other data or code.   The general technique is to
  3018. set  up  a table with a spare 32-bit location  at  its  beginning.
  3019. Then,  when initializing the application's resource,  you move the
  3020. true  \verb"OB_SPEC"  into  this location,  set the  \verb"INDIRECT"  flag,  and
  3021. replace the \verb"OB_SPEC" field with a pointer to the table.  The object
  3022. behaves normally during drawing and form handling. However, if you
  3023. receive  its  number  from  \verb"form_do"  or  \verb"objc_find",  you  have  an
  3024. immediate  pointer to the associated table,  without having to  go
  3025. through a lookup procedure.
  3026.  
  3027.      This  technique works well in programs like the GEM  Desktop.
  3028. Each  \verb"G_ICON" object is set up with \verb"INDIRECT".   Its \verb"OB_SPEC" goes to
  3029. the  beginning of a data area defining the associated  file.   The
  3030. blank  location at the beginning of file table is filled  up  with
  3031. the former \verb"OB_SPEC", which points to a \verb"ICONBLK".
  3032.  
  3033.      You  can also combine \verb"INDIRECT" with \verb"TOUCHEXIT"  when  creating
  3034. objects  that  must change when they are clicked by a  user.   For
  3035. instance,  a  color  selection  box  might be linked  to  a  table
  3036. containing  the various \verb"OB_SPEC" values through which  the  program
  3037. will cycle.   Each time the user clicked on the box, the \verb"TOUCHEXIT"
  3038. routine would advance the table pointer,  copy the next value into
  3039. the  dummy \verb"OB_SPEC" location at the front of the table,  and redraw
  3040. the object in its new appearance.
  3041.  
  3042.      A  programmer  who wanted to follow a  truly  object-oriented
  3043. "Smalltalkish" approach could use the \verb"INDIRECT" method to bind  AES
  3044. drawing  object to tables of associated procedures  or  "methods".
  3045. For instance, one procedure could be flagged for use when the user
  3046. clicked  on the object,  one when the object was dragged,  one for
  3047. double-click,  and  so on.   If the table structure was capable of
  3048. indicating  that  the true method was stored in another  table,  a
  3049. rudimentary form of class inheritance could be obtained.
  3050.  
  3051. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3052. \subsection{Instant co-routines}
  3053.  
  3054.      We turn to the AES event and message system for  this  trick.
  3055. While   some  languages  like  Modula  2  provide  a  method   for
  3056. implementing  co-routines,  there  is  no such  capability  in  C.
  3057. However,  we  can  effectively  fake it by  using  the  AES  event
  3058. library.
  3059.  
  3060.      As  already  seen in an earlier column,  an  application  can
  3061. write a message to its own event queue using the \verb"appl_write"  call.
  3062. Usually, this is a redraw message, but there is nothing to prevent
  3063. you from using this facility to send messages from one routine  in
  3064. your program to another.  To set up co-routines using this method,
  3065. they  would  be  coded  as separate  procedures  called  from  the
  3066. application's main event loop.
  3067.  
  3068.      When  one  of the co-routines wanted to call  the  other,  it
  3069. would  post  a message containing the request and  any  associated
  3070. parameters into the application's queue and then return.  The main
  3071. loop  would find the message and make the appropriate call to  the
  3072. second co-routine.  It it was necessary to then re-enter the first
  3073. co-routine  at  the  calling point,  the  original  message  could
  3074. contain an imbedded reply message to be sent back when the request
  3075. was  complete.   A  simple switch structure could then be used  to
  3076. resume at the appropriate point.
  3077.  
  3078.      There  are two potential problems in using this method.   The
  3079. first is the limited capacity of the application event queue.  The
  3080. queue  contains  eight entries.    While the AES  economizes  this
  3081. space  by  merging redraws and multiple events,  it  cannot  merge
  3082. messages.   Because  of this limit,  you must be extremely careful
  3083. when  one  message received has the potential to generate  two  or
  3084. more  messages sent.   Unless this situation is carefully managed,
  3085. you  can get a sort of "cancer" which will overflow the queue  and
  3086. probably crash your application.
  3087.  
  3088.      The second danger involves race conditions.   Message sent by
  3089. the  application  are posted to the end of the  queue.   If  other
  3090. events  have occurred,  such as mouse clicks or keyboard  presses,
  3091. they will be seen and processed ahead of the application generated
  3092. message.   This  implies  that you cannot use this method  if  the
  3093. program must complete its action before a new user generated event
  3094. can be processed.
  3095.  
  3096. \subsection{Deadlocks}
  3097.  
  3098.      One note on deadlocks: you may have noticed, that sometimes AES
  3099. doesn't react to user input until the mouse button is clicked several
  3100. times. This happens because the GEM is not a true multitasking system.
  3101. The mouse interrupt writes the events into a circular buffer. This
  3102. buffer can store 32 events. If AES is not called for a while, the
  3103. buffer may overflow, resulting in the loss of events. If the event is
  3104. releasing a mouse button, and it is lost, the program is still waiting
  3105. for the button to be released. And the user is confused, because the
  3106. system "hangs".
  3107.  
  3108.      Some sources recommend an \verb"evnt\_timer(0L)" that gives AES
  3109. the chance to empty its event buffer. GEM 2.x provides a call \verb"appl\_yield"
  3110. that has the same result, but needs less time. Fortunately this function
  3111. is also available in Atari's GEM 1.x. In addition to the "magic" values
  3112. \verb"0x73" and \verb"0xC8" for VDI and AES respectively, it's possible
  3113. to assign the value \verb"\0xC9" to Register \verb"D0" before calling the
  3114. GEM trap. That will cause the system to jump directly to the AES internal
  3115. \verb"appl\_yield" routine. Using \verb"appl\_yield" instead of \verb"evnt\_timer"
  3116. will save considerable amounts of time: 1000 calls to \verb"appl\_yield"
  3117. take 1.4 seconds compared to 20 seconds for 1000 calls to \verb"evnt\_timer"!
  3118. Here is an assembly language routine that calls \verb"appl\_yield":
  3119.  
  3120. \begin{verbatim}
  3121. appl_yield:
  3122.         move.w #$C9,d0
  3123.         trap   #2
  3124.         rts
  3125. \end{verbatim}
  3126.  
  3127.     This routine can be added to the GEM-library. It takes no parameter
  3128. and it doesn't return anything. It just keeps the event dispatcher happy.
  3129.  
  3130. \newpage
  3131.  
  3132. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3133. \section{VDI Graphics: Lines and Solids}
  3134.  
  3135.      This chapter of ST PRO GEM will explore the fundamentals of
  3136. VDI graphics  output. We will take a look at the commands necessary to
  3137. output simple graphics such as lines,  squares and circles as well
  3138. as  more complex figures such as polygons.   We will then
  3139.  take a first look at graphics text output,  with an emphasis
  3140. on  ways  to  optimize its drawing speed. As usual,  there is  a
  3141. demonstration program with  this chapter under the name {\tt GEMCL09.C}.
  3142.  
  3143. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3144. \subsection{A bit of history}
  3145.  
  3146.     One  of  the reasons that the VDI can  be  confusing  is  that
  3147. drawing anything at all,  even a simple line,  can involve setting
  3148. around four different VDI parameters before making the draw  call!
  3149. (Given  the state of the GEM documents,  just FINDING them can  be
  3150. fun!)  Looking backwards a bit sheds some light on why the VDI  is
  3151. structured this way,  and also gives us a framework for organizing
  3152. a discussion of graphics output.
  3153.  
  3154.      The GEM VDI closely follows the so-called GKS standard, which
  3155. defines  capabilities  and calling sequences  for  a  standardized
  3156. graphic  input/output system.   GKS is itself an evolution from an
  3157. early system called "Core".   Both of these standards were born in
  3158. the  days  when  pen plotters,  vectored  graphics  displays,  and
  3159. minicomputers  were  the  latest items.   So,  if you  wonder  why
  3160. setting  the drawing pen color is a separate command,  just  think
  3161. back  a  few  years when it actually meant  what  it  says!   (The
  3162. cynical   may   choose   instead  to  ponder   the   benefits   of
  3163. standardization.)
  3164.  
  3165.      When  doing  VDI  output,  it helps if you pretend  that  the
  3166. display screen really is a plotter or some other separate  device,
  3167. which  has  its own internal parameters which you can set  up  and
  3168. read  back.   The class of VDI commands called Attribute Functions
  3169. let  you set the parameters.   Output Functions cause the "device"
  3170. to  actually  draw  someone once it is  configured.   The  Inquire
  3171. Functions let you read back the parameters if necessary.
  3172.  
  3173.      There  are two parameters which are relevant no  matter  what
  3174. type of object you are trying to draw.   They are the writing mode
  3175. and  the clipping rectangle.   The writing mode is similar to that
  3176. discussed in the column on raster operations.   It determines what
  3177. effect the figure you are drawing will have on data already on the
  3178. screen.  The writing mode is set with the call:
  3179.  
  3180. \begin{verbatim}
  3181.           vswr_mode(vdi_handle, mode);
  3182. \end{verbatim}
  3183.  
  3184.    ({\tt vdi\_handle},  here  and  below,  is the  handle  obtained  from
  3185. \verb"graf_handle" at the beginning of the program.  Mode is a word which
  3186. may be one of:
  3187.  
  3188. \begin{description}
  3189. \item[1] Replace Mode
  3190. \item[2] Transparent Mode
  3191. \item[3] XOR mode
  3192. \item[4] Reverse Transparent Mode
  3193. \end{description}
  3194.  
  3195.      In  replace mode,  whatever is on the screen is  overwritten.
  3196. If  you are writing characters,  this means the background of each
  3197. character cell will be erased.
  3198.  
  3199.      In  transparent  mode,  only  the pixels directly  under  the
  3200. "positive"  part  of the image,  that is,  where 1-bits are  being
  3201. written, will be changed.  When writing characters, the background
  3202. of the cell will be left intact.
  3203.  
  3204.      In XOR mode,  an exclusive or is performed between the screen
  3205. contents and what is being written.   The effect is to reverse the
  3206. image under areas where a 1-bit occurs.
  3207.  
  3208.      Reverse transparent is like transparent,  but with a "reverse
  3209. color  scheme".   That  is,  only  places where a 0-bit is  to  be
  3210. put   are  changed  to  the  current  writing  color.    When  you
  3211. write  characters in reverse transparent (over white),  the effect
  3212. is reverse video.
  3213.  
  3214.      The  other  common parameter is the clipping  rectangle.   It
  3215. defines the area on the screen where the VDI is permitted to draw.
  3216. Any output which would fall outside of this area is ignored; it is
  3217. effectively a null operation.   The clip rectangle is set with the
  3218. call:
  3219.  
  3220. \begin{verbatim}
  3221.           vs_clip(vdi_handle, flag, pxy);
  3222. \end{verbatim}
  3223.  
  3224.    {\tt pxy} is a four-word array. \verb"Pxy[0]" and \verb"pxy[1]" are the X and Y
  3225. screen coordinates,  respectively,  of one corner of your clipping
  3226. rectangle.    \verb"Pxy[2]"  and  \verb"pxy[3]"  are  the  coordinates  of   the
  3227. diagonally opposite corner of the rectangle.   (When working  with
  3228. the  AES,  use  of  a  \verb"GRECT" to define  the  clip  is  often  more
  3229. convenient.  The routine \verb"set_clip()" in the listing does this.)
  3230.  
  3231.      {\tt flag} is set to TRUE if clipping is to be used.  If you set it
  3232. to  FALSE,  the  entire  screen is assumed to be fair  game.
  3233.  
  3234.      Normally,  you should walk the rectangle list for the current
  3235. window to obtain your clipping rectangles. 
  3236. However, turning off the clip speeds up all output
  3237. operations,  particularly text.  You may do this ONLY when you are
  3238. absolutely certain that the figure you are drawing will not extend
  3239. out of the top-most window, or out of a dialog.
  3240.  
  3241. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3242. \subsection{The line forms on the left}
  3243.  
  3244.      The  VDI  line  drawing  operations  include  polyline,  arc,
  3245. elliptical  arc,  and rounded rectangle.   I'll first look at  the
  3246. Attribute Functions for line drawing,  then go through the drawing
  3247. primitives themselves.
  3248.  
  3249.      The  most  common used line attributes are color  and  width.
  3250. The color is set with:
  3251.  
  3252. \begin{verbatim}
  3253.           vsl_color(vdi_handle, color);
  3254. \end{verbatim}
  3255.  
  3256.    where color is one of the standard VDI color  indices,  ranging
  3257. from  zero to 15.   (The  color  which
  3258. actually appears will depend on the pallette setting of your ST.)
  3259.  
  3260.      The  line width may only be set to ODD positive  values,  for
  3261. reasons  of  symmetry.   If you try to set an even value,  the VDI
  3262. will take the next lower odd value.  The call is:
  3263.  
  3264. \begin{verbatim}
  3265.           vsl_width(vdi_handle, width);
  3266. \end{verbatim}
  3267.  
  3268.      The  two  less  used line parameters are the  end  style  and
  3269. pattern.   With  the  end style you can cause the output  line  to
  3270. have rounded ends or arrowhead ends.  The call is:
  3271.  
  3272. \begin{verbatim}
  3273.           vsl_ends(vdi_handle, begin_style, end_style);
  3274. \end{verbatim}
  3275.  
  3276.    {\tt Begin\_style} and {\tt end\_style} are each words which  may  have  the
  3277. values zero for square ends (the default),  one for arrowed  ends,
  3278. or  two  for  rounded ends.   They determine the  styles  for  the
  3279. starting and finishing ends of the line, respectively.
  3280.  
  3281.      The line pattern attribute can select dotted or dashed  lines
  3282. as  well  as more complicated patterns.   Before  continuing,  you
  3283. should  note one warning:  VDI line output DOES NOT compensate for
  3284. pixel aspect ratio.  That is, the dashes on a line will look twice
  3285. as long drawn vertically on a medium-res ST screen as they do when
  3286. drawn horizontally.  The command for setting the pattern is:
  3287.  
  3288. \begin{verbatim}
  3289.           vsl_type(vdi_handle, style);
  3290. \end{verbatim}
  3291.  
  3292.    Style  is  a word with a value between 1  and  7.   The  styles
  3293. selected are:
  3294.  
  3295. \begin{description}
  3296. \item[1] Solid (the default)
  3297. \item[2] Long Dash
  3298. \item[3] Dot
  3299. \item[4] Dash, Dot
  3300. \item[5] Dash
  3301. \item[6] Dash, Dot, Dot
  3302. \item[7] (User defined style)
  3303. \end{description}
  3304.  
  3305.    The  user  defined  style is determined  by  a  16-bit  pattern
  3306. supplied  by the application.   A one bit in the pattern  turns  a
  3307. pixel on, a zero bit leaves it off.  The pattern is cycled through
  3308. repeatedly,  using the high bit first.  To use a custom style, you
  3309. must make the call:
  3310.  
  3311. \begin{verbatim}
  3312.           vsl_udsty(vdi_handle, pattern);
  3313. \end{verbatim}
  3314.  
  3315.   before doing \verb"vsl_type()".
  3316.  
  3317.      As  I  mentioned  above,   the  line  type  Output  Functions
  3318. available are polyline,  circular and ellliptical arc, and rounded
  3319. rectangle.   Each  has  its own calling sequence.   The call for a
  3320. polyline is:
  3321.  
  3322. \begin{verbatim}
  3323.           v_pline(vdi_handle, points, pxy);
  3324. \end{verbatim}
  3325.  
  3326.   {\tt points} tells how many vertices will appear on the polyline.  For
  3327. instance,  a  straight  line has two vertices:  the  end  and  the
  3328. beginning.   A closed square would have five,  with the first  and
  3329. last  identical.    (There  is  no  requirement  that  the  figure
  3330. described be closed.)
  3331.  
  3332.      The {\tt pxy} array contains the X and Y raster coordinates for the
  3333. vertices,  with a total of 2 * points entries.   \verb"Pxy[0]" and \verb"pxy[1]"
  3334. are the first X-Y pair, and so on.
  3335.  
  3336.      If you happen to be using the XOR drawing mode, remember that
  3337. drawing  twice  at  a point is equivalent to no  drawing  at  all.
  3338. Therefore,  for  a figure to appear closed in XOR mode,  the final
  3339. stroke  should actually stop one pixel short of the origin of  the
  3340. figure.
  3341.  
  3342.      You  may  notice  that  in the GEM  VDI  manual  the  rounded
  3343. rectangle  and arc commands are referred to as  GDPs  (Generalized
  3344. Drawing Primitives).  This denotation is historical in nature, and
  3345. has  no effect unless you are writing your own VDI bindings.
  3346.  
  3347.      The  rounded rectangle is nice to use for customized  buttons
  3348. in  windows and dialogs.   It gives a "softer" look to the  screen
  3349. than the standard square objects.  The drawing command is:
  3350.  
  3351. \begin{verbatim}
  3352.           v_rbox(vdi_handle, pxy);
  3353. \end{verbatim}
  3354.  
  3355.    {\tt pxy} is a four word array giving opposite corners of the
  3356. rectangle,  just as for the \verb"vs_clip()" call.   The corner  rounding
  3357. occurs  within  the  confines of  this  rectangle.   Nothing  will
  3358. protrude  unless  you specify a line thickness greater  than  one.
  3359. The  corner rounding is approximately circular;  there is no  user
  3360. control over the degree or shape of rounding.
  3361.  
  3362.      Both the arc and elliptical arc commands use a curious method
  3363. of  specifying  angles.   The units are tenths of degrees,  so  an
  3364. entire  circle is 3600 units.   The count starts at ninety degrees
  3365. right of vertical, and proceeds counterclockwise.  This means that
  3366. "3 o'clock" is 0 units,  "noon" is 900 units,  "9 o'clock" is 1800
  3367. units, and 2700 units is at "half-past".  3600 units take you back
  3368. to "3 o'clock".
  3369.  
  3370.      The command for drawing a circular arc is:
  3371.  
  3372. \begin{verbatim}
  3373.           v_arc(vdi_handle, x, y, radius, begin, end);
  3374. \end{verbatim}
  3375.  
  3376.    {\tt x}  and {\tt y} specify the raster coordinates of the  center  of  the
  3377. circle.   {\tt radius} specifies the distance from center to all  points
  3378. on the arc.   {\tt begin} and {\tt end} are angles given in units as described
  3379. above,  both with values between 0 and 3600.   The drawing of  the
  3380. arc  ALWAYS  proceeds  counterclockwise,   in  the  direction   of
  3381. increasing arc number.   So values of 0 and 900 for begin and  end
  3382. would  draw  a  quarter circle from  "three  o'clock"  to  "noon".
  3383. Reversing  the values would draw the other three quarters  of  the
  3384. circle.
  3385.  
  3386.      A  \verb"v_arc()"  command  which specifies a  "full  turn"  is  the
  3387. fastest  way to draw a complete circle on the screen.   Be warned,
  3388. however,  that  the circle drawing algorithm used in the VDI seems
  3389. to  have  some  serious  shortcomings at  small  radii!   You  can
  3390. experiment  with  the  CIRCLE primitive in  ST  Logo,  which  uses
  3391. \verb"v_arc()", to see what I mean.
  3392.  
  3393.      Notice  that if you want an arc to strike one or more  given
  3394. points on the screen,  then you are in for some trigonometry.   If
  3395. your  math  is  a  bit  rusty,  I highly  recommend  the  book  "A
  3396. Programmer's  Geometry",  by  Bowyer  and Woodwark,  published  by
  3397. Butterworths (London, Boston, Toronto).
  3398.  
  3399.      Finally, the elliptical arc is generated with:
  3400.  
  3401. \begin{verbatim}
  3402.           v_ellarc(vdi_handle, x, y, xrad, yrad, begin, end);
  3403. \end{verbatim}
  3404.  
  3405.  {\tt y}, {\tt y},  {\tt begin}, and {\tt end} are just as before.  
  3406. {\tt xrad}\/ and {\tt yrad} give the
  3407. horizontal and vertical radii of the defining ellipse.  This means
  3408. that  the distance of the arc from center will be {\tt yrad} pixels  at
  3409. "noon"  and  "half-past",  and it will be {\tt xrad} pixels at "3 and  9
  3410. o'clock".  Again, the arc is always drawn counterclockwise.
  3411.  
  3412.      There  are  a  number  of approaches  to  keeping  the  VDI's
  3413. attributes "in sync" with the actual output operations.   Probably
  3414. the  LEAST efficient is to use the Inquire Functions to  determine
  3415. the  current  attributes.   For  this  reason,  I have  omitted  a
  3416. discussion of these calls from this chapter.
  3417.  
  3418.      Another  idea  is  to keep a local copy  of  all  significant
  3419. attributes, use a test-before-set method to minimize the number of
  3420. Attribute  Functions which need to be called.   This puts a burden
  3421. on  the programmer to be sure that the local  attribute  variables
  3422. are correctly maintained.   Failure to do so may result in obscure
  3423. drawing  bugs.   If  your  application employs  user  defined  AES
  3424. objects, you must be very careful because GEM might call your draw
  3425. code  in the middle of a VDI operation (particularly if  the  user
  3426. defined objects are in the menu).
  3427.  
  3428.      Always  setting  the attributes is a simplistic  method,  but
  3429. often   proves  most  effective.    The  routines  \verb"pl_perim()"  and
  3430. \verb"rr_perim()"  in the listing exhibit this  approach.   Modification
  3431. for  other  primitives  is straightforward.   This style  is  most
  3432. useful  when  drawing  operations  are  scattered  throughout  the
  3433. program,  so that keeping track of the current attribute status is
  3434. difficult.  Although inherently inefficient, the difference is not
  3435. very  noticable if the drawing operation requested is itself  time
  3436. consuming.
  3437.  
  3438.      In  many  applications,  such  as data graphing  programs  or
  3439. "Draw"  packages,  the output operations are centralized,  forming
  3440. the primary functionality of the code.   In this case,  it is both
  3441. easy  and  efficient  to keep track of  attribute  status  between
  3442. successive drawing operations.
  3443.  
  3444. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3445. \subsection{Solids}
  3446.  
  3447.     There  are  a wider variety of VDI  calls  for  drawing  solid
  3448. figures.   They  include rectangle or  bar,  disk,  pie,  ellipse,
  3449. elliptical  pie,  filled rounded rectangle,  and filled  polygonal
  3450. area.   Of course,  filled figure calls also have their own set of
  3451. attributes which you will need to set.
  3452.  
  3453.      The  fill color index determines what pen color will be  used
  3454. to draw the solid.  It is set with:
  3455.  
  3456. \begin{verbatim}
  3457.           vsf_color(vdi_handle, color);
  3458. \end{verbatim}
  3459.  
  3460.      {\tt color} is just the same as for line drawing.   A solid may  or
  3461. may not have a visible border.  This is determined with the call:
  3462.  
  3463. \begin{verbatim}
  3464.           vsf_perimeter(vdi_handle, vis);
  3465. \end{verbatim}
  3466.  
  3467.    {\tt vis} is a Boolean.   If it is true,  the figure will be given  a
  3468. solid one pixel outline in the current fill color index.   This is
  3469. often  useful  to improve the appearance of solids  drawn  with  a
  3470. dithered fill pattern.  If {\tt vis}\/ is false, then no outline is drawn.
  3471.  
  3472.      There are two parameters which together determine the pattern
  3473. used  to  fill your figure.   They are called interior  style  and
  3474. interior  index.   The style determines the general type of  fill,
  3475. and the index is used to select a particular pattern if necessary.
  3476. The style is set with the command:
  3477.  
  3478. \begin{verbatim}
  3479.           vsf_interior(vdi_handle, style);
  3480. \end{verbatim}
  3481.  
  3482.   where {\tt style}\/ is a value from zero through four.   Zero selects  a
  3483. hollow  style:  the  fill is performed in  color  zero,  which  is
  3484. usually  white.   Style one selects a solid fill with the  current
  3485. fill  color.   A style of two is called "pattern" and a  three  is
  3486. called "hatch", which are terms somewhat suggestive of the options
  3487. which can then be selected using the interior index.   Style  four
  3488. selects the user defined pattern, which is described below.
  3489.  
  3490.      The  interior  index is only significant for styles  two  and
  3491. three. To set it, use:
  3492.  
  3493. \begin{verbatim}
  3494.           vsf_style(vdi_handle, index);
  3495. \end{verbatim}
  3496.  
  3497.    (Be careful here: it is very easy to confuse this call with the
  3498. one  above  due  to the unfortunate choice of  name.)   The {\tt  index}\/ 
  3499. selects the actual drawing pattern.  The GEM VDI manual shows fill
  3500. patterns corresponding to index values from 1 to 24 under style 2,
  3501. and  from  1 to 12 under style 3.   However,  some  of  these  are
  3502. implemented  differently on the ST.   Rather than try to  describe
  3503. them all here, I would suggest that you experiment.  You can do so
  3504. easily  in  ST Logo by opening the Graphics  Settings  dialog  and
  3505. playing with the style and index values there.
  3506.  
  3507.      The user defined style gives you some interesting options for
  3508. multi-color fills.  It is set with:
  3509.  
  3510. \begin{verbatim}
  3511.           vsf_udpat(vdi_handle, pattern, planes);
  3512. \end{verbatim}
  3513.  
  3514.     {\tt planes}  determines the number of color planes in  the  pattern
  3515. which  you  supply.   It  is  set to one  if  you  are  setting  a
  3516. monochrome  pattern.   (Remember,  monochrome is  not  necessarily
  3517. black).   It may be set to higher values on color systems: two for
  3518. ST medium-res mode, or four for low-res mode.  If you use a number
  3519. lower than four under low-res, the other planes are zero filled.
  3520.  
  3521.      The {\tt pattern} parameter  is  an array of  words  which  is  a
  3522. multiple  of  16 words long.  The pattern determined is 16  by  16
  3523. pixels,  with each word forming one row of the pattern.   The rows
  3524. are  arranged top to bottom,  with the most significant bit to the
  3525. left.   If  you  have selected a multi-plane pattern,  the  entire
  3526. first plane is stored, then the second, and so on.
  3527.  
  3528.        Note that to use a multi-plane pattern, you set the writing
  3529. mode  to replace using \verb"vswr_mode()".   Since the each plane can  be
  3530. different,  you can produce multi-colored patterns.   If you use a
  3531. writing   color  other  than  black,   some  of  the  planes   may
  3532. "disappear".
  3533.  
  3534.      Most  of  the  solids Output Functions  have  analogous  line
  3535. drawing commands.   The polyline command corresponds to the filled
  3536. area primitive.  The filled area routine is:
  3537.  
  3538. \begin{verbatim}
  3539.           v_fillarea(vdi_handle, count, pxy);
  3540. \end{verbatim}
  3541.  
  3542.     {\tt count}  and {\tt pxy} are just the same as  for  \verb"v_pline()".   If  the
  3543. polygon  defined  by \verb"pxy" is not closed,  then the VDI  will  force
  3544. closure  with  a straight line from the last to the  first  point.
  3545. The  polygon may  be concave or self-intersecting.   If  perimeter
  3546. show is on, the area will be outlined.
  3547.  
  3548.      One  note of caution is necessary for both  \verb"v_fillarea()"  and
  3549. \verb"v_pline()".   There is a limit on the number of points which may be
  3550. stored in \verb"pxy[]".   This limit occurs because the contents of \verb"pxy[]"
  3551. are copied to the \verb"intin[]" binding array before the VDI is  called.
  3552. You  can  determine  the maximum number of  vertices  by  checking
  3553. \verb"intout[14]" after using the extended inquire function \verb"vq_extnd()".
  3554.  
  3555.      For  reasons unknown to this writer,  there are TWO different
  3556. filled rectangle commands in the VDI.  The first is
  3557.  
  3558. \begin{verbatim}
  3559.           vr_recfl(vdi_handle, pxy);
  3560. \end{verbatim}
  3561.  
  3562.     {\tt Pxy} is a four word array defining two opposite corners of  the
  3563. rectangle,  just  as  in  \verb"vs_clip()".   \verb"Vr_recfl()"  uses  the  fill
  3564. attribute settings, except that it NEVER draws a perimeter.
  3565.  
  3566.      The other rectangle routine is \verb"v_bar()", with exactly the same
  3567. arguments  as  \verb"vr_recfl()".    The  only  difference  is  that  the
  3568. perimeter  setting  IS  respected.   These two  routines  are  the
  3569. fastest way to produce a solid rectangle using the VDI.   They may
  3570. be  used in XOR mode with a BLACK fill color to quickly invert  an
  3571. area  of  the screen.   You can improve the speed even further  by
  3572. turning off the clip (if possible), and byte aligning the left and
  3573. right edges of the rectangle.
  3574.  
  3575.      Separate commands are provided for solid circle and  ellipse.
  3576. The circle call is:
  3577.  
  3578. \begin{verbatim}
  3579.           v_circle(vdi_handle, x, y, radius);
  3580. \end{verbatim}
  3581.  
  3582.    and the ellipse command is:
  3583.  
  3584. \begin{verbatim}
  3585.           v_ellipse(vdi_handle, x, y, xrad, yrad);
  3586. \end{verbatim}
  3587.  
  3588.     All of the parameters are identical to those given  above  for
  3589. \verb"v_arc()"  and \verb"v_ellarc()".   The solid analogue of an arc is a  "pie
  3590. slice".  The VDI pie commands are:
  3591.  
  3592. \begin{verbatim}
  3593.           v_pieslice(vdi_handle, x, y, radius, begin, end);
  3594. \end{verbatim}
  3595.  
  3596.   for a slice from a circular pie, and
  3597.  
  3598. \begin{verbatim}
  3599.           v_ellpie(vdi_handle, x, y, xrad, yrad, begin, end);
  3600. \end{verbatim}
  3601.  
  3602.    for a slice from a "squashed" pie.   Again,  the parameters are
  3603. identical  to  those in \verb"v_arc()" and  \verb"v_ellarc()".   The  units  and
  3604. drawing  order  of angles are also the  same.   The  final  solids
  3605. Output Function is:
  3606.  
  3607. \begin{verbatim}
  3608.           v_rfbox(vdi_handle, pxy);
  3609. \end{verbatim}
  3610.  
  3611.   which draws a filled rounded rectangle.   The {\tt pxy}\/ array  defines
  3612. two  two  opposite  corners of the  bounding  box,  as  shown  for
  3613. \verb"vs_clip()".
  3614.  
  3615.      The  issues involved in correctly setting the VDI  attributes
  3616. for a fill operation are identical to those in drawing lines.  For
  3617. those  who  want to employ the "always set" method,  I have  again
  3618. included  two  skeleton  routines in the listing,  which  can  be
  3619. modified as desired.
  3620. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3621.  
  3622. \newpage
  3623. \section{VDI Graphics: Text Output}
  3624.  
  3625. We will now look at simple VDI  text output,  and ways to optimize
  3626. its  speed. To  keep  the size of this first discussion  of  text  within
  3627. reason, I am going to restrict it to use of the mono-spaced system
  3628. font   in  its  default  size  and  orientation.    Discussion  of
  3629. alternate and proportionally spaced fonts,  baseline rotation, and
  3630. character scaling will be a later chapter. Sample code is provided
  3631. in {\tt GEMCL10.C}.
  3632.  
  3633. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3634. \subsection{Definitions}
  3635.  
  3636. This chapter  makes use of  some  terminology
  3637. which may be unfamiliar if you have not used digital typefaces.  A
  3638. mono-spaced  font  is  one in which  each  character  occupies  an
  3639. identically  wide  space on the screen.   A proportional font  has
  3640. characters  which occupy different widths.   For instance,  an 'l'
  3641. would probably be narrower than a 'w'.
  3642.  
  3643.     Text may be "justified" right,  left,  or center.  This means
  3644. that  the right character,  left character,  or center position of
  3645. the  text  string is constrained to a given location.   In  common
  3646. usage,  a  page  of text is "ragged right" if its lines  are  left
  3647. justified only.   The text page is "fully justified",  "justified"
  3648. or  (ambiguously)  "right justified" if BOTH the  left  and  right
  3649. characters are contrained to fixed columns.  Full justification is
  3650. produced  by  inserting extra blank characters in the  case  of  a
  3651. mono-spaced font,  or by adding extra pixel columns in the case of
  3652. proportional output.
  3653.  
  3654.      A  text character (in a monospaced font) is written inside  a
  3655. standard sized cell or box.  Vertically, the cell extends from the
  3656. "top  line" down to the "bottom line".   If there are one or  more
  3657. blank  lines at the top or bottom,  they are called "leading"  and
  3658. are  used  to separate lines of text.   The characters  themselves
  3659. always  fall between the "ascent line",  which is the highest line
  3660. reached by characters such as 'd' and 'l', and the "descent line",
  3661. which  is the lowest line in characters like 'q' and  'g'.   Other
  3662. locations  of  interest are the "half line",  which is the top  of
  3663. characters  like  'a' or 'n',  and the "base line",  which is  the
  3664. bottom of characters which do not have descenders.
  3665.  
  3666.      Before  plunging into the Attribute Functions for  text,  you
  3667. should  note  that  the  writing  mode  (\verb"vswr_mode")  and  clipping
  3668. rectangle  (\verb"vs_clip") attributes discussed earlier
  3669. also  pertain  to  text.   Since much of the  discussion  of  text
  3670. optimization  will  center on these attributes,  you may  want  to
  3671. review them.
  3672.  
  3673. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3674. \subsection{Text attributes}
  3675.  
  3676. The writing color for graphics text is set
  3677. with the command:
  3678.  
  3679. \begin{verbatim}
  3680.           vst_color(vdi_handle, color);
  3681. \end{verbatim}
  3682.  
  3683. {\tt color} is a word value between 0 and 15 which
  3684. designates  the  output  color index.   As discussed  in  previous
  3685. columns,  the  actual  color  which appears is  dependent  on  the
  3686. current  palette  settings.   In  applications such  as  word  and
  3687. outline  processors  it  is important that  characters  and  their
  3688. background  provide  good contrast to avoid eyestrain.   In  these
  3689. situations,  you  may  want to use the \verb"setPalette" and/or  \verb"setColor"
  3690. XBIOS  functions  to  force the palette to a  known  state  before
  3691. starting the application.
  3692.  
  3693.      You  can choose a variety of special output effects for  your
  3694. text with the call:
  3695.  
  3696. \begin{verbatim}
  3697.           vst_effects(vdi_handle, effects);
  3698. \end{verbatim}
  3699.  
  3700. {\tt effects} is a single flag word,  with the bits having the following
  3701. significance:
  3702.  
  3703. \begin{description}
  3704. \item[0] Thicken
  3705. \item[1] Lighten
  3706. \item[2] Skew
  3707. \item[3] Underline
  3708. \item[4] Outline
  3709. \item[5] Shadow
  3710. \end{description}
  3711.  
  3712. In each case,  turning the bit on selects the effect.   Otherwise,
  3713. the  effect  is  off.   Any  number of  multiple  effects  may  be
  3714. selected, but the result may not always be pleasing or legible.
  3715.  
  3716.      The  "thicken"  effect widens the character  strokes  by  one
  3717. pixel,   resulting  in  the  appearance  of  boldface  type.   The
  3718. "lighten" effect superimposes a half-tone dither on the character.
  3719. This mode is useful for indicating non-selectable text items,  but
  3720. is not legible enough for other purposes.
  3721.  
  3722.      The  skew effect shifts the rows of the character the  right,
  3723. with  the greatest displacement at the top.   This results in  the
  3724. appearance of italic text.   You should be aware that the VDI does
  3725. not  compensate for this effect.   This means that a skewed italic
  3726. character which is immediately followed by a normal blank will  be
  3727. overstruck,  and  part of the top of the character will disappear.
  3728. Likewise,  a  skewed character written to the left of an  existing
  3729. normal  character will overstrike part of it.   There is a related
  3730. bug  in  the VDI clipping logic which may cause some  parts  of  a
  3731. skewed  character not to be redrawn if they fall at the edge of  a
  3732. clipping  rectangle,  even  though  they should  fall  within  the
  3733. region.
  3734.  
  3735.      The  outline  effect  produces output which is  a  one  pixel
  3736. "halo" around the normal character.  The shadow effect attempts to
  3737. create  a  "drop  shadow" to the side  of  the  character.   These
  3738. effects  should be used very sparingly with default  sized  fonts.
  3739. They often result in illegible output.
  3740.  
  3741.      When  graphics text is written,  a screen coordinate must  be
  3742. specified  for  the output.   The relationship of the text to  the
  3743. screen point is determined by the call:
  3744.  
  3745. \begin{verbatim}
  3746.           vst_alignment(vdi_handle, hin, vin, &hout, &vout);
  3747. \end{verbatim}
  3748.  
  3749. {\tt hin}  and  {\tt vin} are each words,  with values specifying the  desired
  3750. horizontal  and vertical alignment,  respectively.   {\tt hout}\/ and
  3751.  {\tt vout}
  3752. receive the actual values set by the VDI.  If they differ from the
  3753. requested values, an error has occurred.
  3754.  
  3755.      {\tt in} may be set to zero for left justification, one for center
  3756. justification,  or  two  for right justification.   The coordinate
  3757. given when text is written becomes the "anchor point" as described
  3758. in the definitions above.  The default justification is left.
  3759.  
  3760.      {\tt vin} determines what reference line of the text is  positioned
  3761. at the output coordinate.  The selection values are:
  3762.  
  3763. \begin{description}
  3764. \item[0] baseline (default)
  3765. \item[1] half line
  3766. \item[2] ascent line
  3767. \item[3] bottom line
  3768. \item[4] descent line
  3769. \item[5] top line
  3770. \end{description}
  3771.  
  3772.      A  common combination of alignments is left (0) and top  line
  3773. (5).   This  mode guarantees that all text output will lie to  the
  3774. right and below the output coordinate.   This corresponds with the
  3775. AES object and \verb"GRECT" coordinate systems.
  3776.  
  3777.      Finally, the call to do the actual output is:
  3778.  
  3779. \begin{verbatim}
  3780.           v_gtext(vdi_handle, x, y, string);
  3781. \end{verbatim}
  3782.  
  3783. {\tt x}  and {\tt y} define the screen coordinate to be used as the  alignment
  3784. point.   {\tt string}  is  a pointer to a null terminated string,  which
  3785. must  be total eighty characters or less,  exclusive of the  null.
  3786. This limit is imposed by the size of the \verb"intin[]" array in the  VDI
  3787. binding.   Be  warned  that  it  is NOT checked  in  the  standard
  3788. binding!  Exceeding it may cause memory to be overwritten.
  3789.  
  3790.      One Inquire Function is useful with text output.  The call
  3791.  
  3792. \begin{verbatim}
  3793.           vqt_attributes(vdi_handle, attrib);
  3794. \end{verbatim}
  3795.  
  3796. reads  back the current attribute settings into the 10 word  array
  3797. \verb"attrib[]".   The  main  items  of interest  are  \verb"attrib[6]"  through
  3798. \verb"attrib[9]",  which contain the width and height of characters,  and
  3799. the  width and height of the character cell in the  current  font.
  3800. You  should  rely  on this function to  obtain  size  information,
  3801. rather  than using the output of the \verb"graf_handle()"  function.   On
  3802. the ST, \verb"graf_handle()" always returns sizes for the monochrome mode
  3803. system font, which will be incorrect in the color screen modes.
  3804.  
  3805.      \verb"Attrib[1]" will contain the current graphics text color as set
  3806. by  \verb"vst_color()".   \verb"Attrib[3]"  and \verb"[4]" contain the  horizontal  and
  3807. vertical alignment settings, respectively.  \verb"Attrib[5]" contains the
  3808. current writing mode, as set by \verb"vswr_mode()".
  3809.  
  3810. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3811. \subsection{Optimization}
  3812.  
  3813. The most common complaint about using bit maps
  3814. for character output is lack of speed.  This section suggests ways
  3815. to  speed  things up.   By adopting all of these methods,  you can
  3816. realize an improvement of two to three times in speed.
  3817.  
  3818. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3819. \subsubsection{Byte alignment}
  3820.  
  3821. Since writing graphic text is essentially a
  3822. bit-blit operation,  characters which have "fringes",  that is, do
  3823. not  align  evenly with byte boundaries,  will suffer  performance
  3824. penalities.  The default system fonts in all resolutions of the ST
  3825. are  a  multiple of eight pixels wide,  so the problem reduces  to
  3826. assuring  that  each characters starts at a byte boundary  in  the
  3827. screen bit map.  This will be true if the horizontal pixel address
  3828. of the left edge of the character is evenly divisible by eight.
  3829.  
  3830.      Obviously,  byte  alignment  is easiest to enforce  when  the
  3831. horizontal justification is right or left.  Doing so with centered
  3832. text is possible, but requires adding padding blanks to odd length
  3833. strings.
  3834.  
  3835.      When  writing  text within windows,  it is helpful to  assure
  3836. that the edges of the window working area are byte aligned.  There
  3837. is  a section of code in the listing which shows a technique  for
  3838. converting  a  user requested window position and/or size  to  its
  3839. working   dimensions,   byte-aligning  the  width  and  horizontal
  3840. position, and computing the adjusted external window coordinates.
  3841.  
  3842. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3843. \subsubsection{Writing Mode}
  3844.  
  3845. The fastest text output mode is replace.  All
  3846. other modes require reading in the target raster area and  merging
  3847. it  with  the  new information.   You may find that you  must  use
  3848. transparent or reverse transparent mode,  for instance,  to use or
  3849. preserve an underlying background color other than white.  In this
  3850. case,  you  can  still  do  some optimization by  filling  in  the
  3851. background color for the entire string with a \verb"v_bar()" call, rather
  3852. than doing it one character cell at a time.
  3853.  
  3854. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3855. \subsubsection{Clipping}
  3856.  
  3857. VDI  output  always  proceeds  faster  when  the
  3858. clipping rectangle is turned off, and text output is no exception.
  3859. Remember  that  you  may only do this if you are  drawing  into  a
  3860. dialog box,  or into the interior of a window which you know is on
  3861. top.   (You  can  use  the \verb"WM_TOPPED" and  \verb"WM_NEWTOP"  messages  for
  3862. keeping track of the top window, or use the \verb"WF_TOP wind_get()" call
  3863. to  find the current top.)  In both of these cases,  you will know
  3864. the  width  of the drawing area,  and you can truncate the  output
  3865. string to fit exactly, rather than setting the clipping rectangle.
  3866. For this to work,  you must have used the byte alignment technique
  3867. to  assure  that the width of the writing area is  a  multiple  of
  3868. eight. The VDI will also run at the non-clipped speed  if
  3869. the  ENTIRE  string  to  be written is  within  the  current  clip
  3870. rectangle.  To compound the problem, there is a one-off bug in the
  3871. detection  algorithm  for  the right  edge.   That  is,  the  clip
  3872. rectangle  has to be one pixel BEYOND the right edge of  the  text
  3873. for the fast write to work.
  3874.  
  3875. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3876. \subsubsection{Bindings}
  3877.  
  3878. The  normal binding for \verb"v_gtext()" is inefficient.
  3879. It copies the string which you supply character-by-character  into
  3880. \verb"intin[]" before it calls the VDI itself.  In many cases, it will be
  3881. more  efficient for your application to place characters  directly
  3882. into \verb"intin[]" and make the VDI trap call directly.   To give you a
  3883. start,  the  code  for  the standard \verb"v_gtext()"  binding  has  been
  3884. included in the listing.  When setting up \verb"intin[]", be sure not to
  3885. load  more  than  80 characters,  or you will probably  crash  the
  3886. system!
  3887.  
  3888. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3889. \subsubsection{Moving text}
  3890.  
  3891. When performing text editing on the screen, you
  3892. should  avoid rewriting the string under edit  whenever  possible.
  3893. It is always more efficient to use the raster operations to move a
  3894. string  to  the right or left,  assuming that you have obeyed  the
  3895. byte  alignment rule.    If you are deleting characters,  blit the
  3896. unchanged part of the screen to the left,  and overstrike the last
  3897. character  in the string with a blank.   If inserting  characters,
  3898. blit  the  trailing  portion of the string  to  the  right  before
  3899. writing in the new character.
  3900.  
  3901. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3902. \subsection{By the way$\ldots$}
  3903.  
  3904.      It turns out there is an undocumented feature in
  3905. Alcyon  C  which allows you to imbed assembly code  in-line.   Try
  3906. using:
  3907.  
  3908. \begin{verbatim}
  3909.      asm(".....");
  3910. \end{verbatim}
  3911.  
  3912. where the dots are replaced with an assembly instruction.  You get
  3913. one instruction per \verb"asm()",  one \verb"asm()" per line.
  3914.  
  3915.  
  3916. \newpage
  3917.  
  3918. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3919. \section{Computer - Human Interface}
  3920.  
  3921. \centerline{\bf And now for something completely different!}
  3922.  
  3923. This chapter of ST Professional GEM will be devoted
  3924. to examining a few of the principles of computer/human interface
  3925. design, or "religion" as some would have it.  I'm going to start
  3926. with basic ergonomic laws, and try to draw some conclusions which
  3927. are fairly specific to designing for the ST.
  3928.  
  3929.      For those who did not pray for this topic, it seems fair to
  3930. explain why your diet of hard-core technical information has been
  3931. interrupted by a sermon!  As a motivater, we might consider why
  3932. some programs are said by reviewers to have a "hot" feel (and
  3933. hence sell well!) while others are "confusing" or "boring".
  3934.  
  3935.      Alan Kay has said that "user interface is theatre".  I think
  3936. we may be able to take it further, and suggest that a successful
  3937. program works a bit of magic, persuading the user to suspend his
  3938. disbelief and enter an imaginary world behind the screen, whether
  3939. it is the mathematical world of a spreadsheet, or the land of Pacman
  3940. pursued by ghosts.
  3941.  
  3942.      A reader of a novel or science fiction story also suspends
  3943. disbelief to participate in the work.  Bad grammar and clumsy plotting
  3944. by the author are jarring, and break down the illusion.  Similarly,
  3945. a programmer who fails to pay attention to making his interface
  3946. fast and consistent will annoy the user, and distract him from
  3947. whatever care has been lavished on the functional core of the program.
  3948.  
  3949. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3950. \subsection{Credit where it's due}
  3951.  
  3952.   Before launching into the discussion
  3953. of user interface, I should mention that the general treatment and
  3954. many of the specific research results are drawn from Card, Newell,
  3955. and Moran's landmark book on the topic, which is cited at the end
  3956. of this chapter.  Any errors in interpretation and application to
  3957. GEM and the ST are entirely my own, however.
  3958.  
  3959. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3960. \subsection{Fingertips}
  3961.  
  3962.   We'll start right at the user's fingers with the
  3963. basic equation governing positioning of the mouse, Fitt's Law,
  3964. which is given as
  3965.  
  3966. \begin{equation}
  3967.      T = I \cdot \log_2( \frac{D}{S} + \frac{1}{2})
  3968. \end{equation}
  3969.  
  3970.  where T is the amount of time to move to a target, D is the distance
  3971. of the target from the current position, and S is the size of the
  3972. target, stated in equivalent units.  $\log_2$ is the base 2 (binary)
  3973. logarithm function, and I is a proportionality constant, about
  3974. 100 milliseconds per bit, which corresponds to the human's "clock
  3975. rate" for making incremental movements.
  3976.  
  3977.      We can squeeze an amazing amount of information out of this
  3978. formula when attempting to speed up an interface.  Since motion time
  3979. goes up with distance, we should arrange the screen with the
  3980. usual working area near the center, so the mouse will have to move
  3981. a smaller distance on average from a selected object to a menu or
  3982. panel.  Likewise, any items which are usually used together should
  3983. be placed together.
  3984.  
  3985.      The most common operations will have the greater impact on
  3986. speed, so they should be closest to the working area and perhaps
  3987. larger than other icons or menu entries.  If you want to have
  3988. all other operations take about the same time, then the targets
  3989. farthest from the working area should be larger, and those closer
  3990. may be proportionately smaller.
  3991.  
  3992.      Consider also the implications for dialogs.  Small check boxes
  3993. are out.  Large buttons which are easy to hit are in.  There should
  3994. be ample space between selectable items to allow for positioning
  3995. error.  Dangerous options should be widely separated from common
  3996. selections.
  3997.  
  3998. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3999. \subsection{Muscles}
  4000.  
  4001.  Anyone who has used the ST Desktop for any period
  4002. of time has probably noticed that his fingers now know where to find
  4003. the File menu.  This phenomenon is sometimes called "muscle memory",
  4004. and its rate of onset is given by the Power Law of Practice:
  4005.  
  4006. \begin{equation}
  4007.      T(n) = T(1) \cdot {n^{-a}}
  4008. \end{equation}
  4009.  
  4010. where T(n) is the time on the nth trial, T(1) is the time on the
  4011. first trial, and a is approximately 0.4.
  4012.  
  4013.      This first thing to note about the Power Law is that it only
  4014. works if a target stays in the same place!  This should be a potent
  4015. argument against rearranging icons, menus, or dialogs without some
  4016. explicit request by the user.  The time to hit a target which moves
  4017. around arbitrarily will always be T(1)!
  4018.  
  4019.      In many cases, the Power Law will also work for sequences of
  4020. operations to even greater effect.  If you are a touch typist, you
  4021. can observe this effect by comparing how fast you can enter "the"
  4022. in comparison to three random letters.  We'll come back shortly
  4023. to consider what we can do to encourage this phenomenon.
  4024.  
  4025. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4026. \subsection{Eyes}
  4027.  
  4028.   Just as fingers are the way the user sends data to the
  4029. computer, so the eyes are his channel from the machine.  The rate
  4030. at which information may be passed to the user is determined by
  4031. the "cycle time" of his visual processor.  Experimental results
  4032. show that this time ranges between 50 and 200 milliseconds.
  4033.  
  4034.      Events separated by 50 milliseconds or less are always
  4035. perceived as a single event.  Those separated by more than 200
  4036. milliseconds are always seen as separate.  We can use these
  4037. facts in optimizing user of the computer's power when driving the
  4038. interface.
  4039.  
  4040.      Suppose your application's interface contains an icon which
  4041. should be inverted when the mouse passes over it.  We now know
  4042. that flipping it within one twentieth of a second is necessary
  4043. and sufficient.  Therefore, if a "first cut" at the program achieves
  4044. this performance, there is no need for further optimization, unless
  4045. you want to interleave other operations.  If it falls short, it will
  4046. be necessary to do some assembly coding to achieve a smooth feel.
  4047.  
  4048.      On the other hand, two actions which you want to appear distinct
  4049. or convey two different pieces of information must be separated
  4050. by an absolute minimum of a fifth of a second, even assuming that
  4051. they occur in an identical location on which the user's attention
  4052. is already focused.
  4053.  
  4054.      We are able to influence the visual processing rate within the
  4055. 50 to 200 millisecond range by changing the intensity of the stimulus
  4056. presented.  This can be done with color, by flashing a target, or
  4057. by more subtle enhancements such as bold face type.  For instance,
  4058. most people using GEM soon become accustomed to the "paper white"
  4059. background of most windows and dialogs.  A dialog which uses a
  4060. reverse color scheme, white letters on black, is visually shocking
  4061. in its starkness, and will immediately draw the user's eyes.
  4062.  
  4063.      It should be quickly added that stimulus enhancement will only
  4064. work when it unambiguously draws attention to the target.  Three or
  4065. four blinking objects scattered around the screen are confusing, and
  4066. worse than no enhancement at all!
  4067.  
  4068. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4069. \subsection{Short-term memory}
  4070.  
  4071.   Both the information gathered by the eyes
  4072. and movement commands on their way to the hand pass through short-term
  4073. memory (also called working memory).  The amount of information which
  4074. can be held in short-term memory at any one time is limited.  You can
  4075. demonstrate this limit on yourself by attempting to type a sheet of
  4076. random numbers by looking back and forth from the numbers to the
  4077. screen.  If you are like most people, you will be able to remember
  4078. between five and nine numbers at a time.  So universal is this
  4079. finding that it is sometimes called "the magic number seven, plus
  4080. or minus two".
  4081.  
  4082.      This short-term capacity sets a limit on the number of choices
  4083. which the user can be expected to grasp at once.  It suggests that
  4084. the number of independent choices in a menu, for instance, should
  4085. be around seven, and never exceed nine.  If this limit is violated,
  4086. then the user will have to take several glances, with pauses to
  4087. think, in order to make a choice.
  4088.  
  4089. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4090. \subsection{Chunking}
  4091.  
  4092.   The effective capacity of short-term memory can be
  4093. increased when several related items are mentally grouped as a "chunk".
  4094. Humans automatically adopt this strategy to save themselves time.
  4095. For instance, random numbers had to be used instead of text in the
  4096. example above, because people do not type their native language as
  4097. individual characters.  Instead, they combine the letters into words
  4098. and remember these chunks instead.  Put another way, the characters
  4099. are no longer considered as individual choices.
  4100.  
  4101.      A well designed interface should promote the use of chunking
  4102. as a strategy by the user.  One easy way is to gather together
  4103. related options in a single place.  This is one reason that like
  4104. commands are grouped into a single menu which is hidden except for
  4105. its title.  If all of the menu options were "in the open", the user
  4106. would be overwhelmed with dozens of alternatives at once.  Instead, a
  4107. "Show Info" command, for instance, becomes two chunks: pick File
  4108. menu, then pick Show.
  4109.  
  4110.      Sometimes the interface can accomplish the chunking for the user.
  4111. Consider the difference between a slider bar in a GEM program, and
  4112. a three digit entry field in a text mode application.  Obviously,
  4113. the GEM user has fewer decisions to make in order to set the associated
  4114. variable.
  4115.  
  4116. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4117. \subsection{Think!}
  4118.  
  4119.   While we are puttering around trying to speed up
  4120. the keyboard, the mouse, and the screen, the user is actually
  4121. trying to get some work done.  We need to back off now, and
  4122. look at the ways of thinking, or cognitive processes, that go into
  4123. accomplishing the job.
  4124.  
  4125.      The user's goal may be to enter and edit a letter, to retrieve
  4126. information from a database, or simply draw a picture, but it
  4127. probably has very little to do with programming.  In fact, the
  4128. Problem Space Principle says that the task can be described as
  4129. a set of states of knowledge, a set of operators and associated
  4130. constraints for changing the states, and the knowledge to
  4131. choose the appropriate operator, which resides in the user's head.
  4132.  
  4133.      Those with a background in systems theory can consider this
  4134. as a somewhat abstract, but straightforward, statement in terms of
  4135. state variables and operators.  A programmer might compare the
  4136. knowledge states to the values of variables, the operators to
  4137. arithmetic and logic operations, the constraints to the rules of
  4138. syntax, and the user's knowledge to the algorithm embodied by a
  4139. program.
  4140.  
  4141. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4142. \subsection{Are we not men?}
  4143.  
  4144.   A rational person will try to attain his
  4145. goals (get the job done) by changing the state of his problem space
  4146. from its initial state to the goal state.  The initial state,
  4147. for instance, might be a blank word processor screen.  The desired
  4148. final state is to have a completed business letter on the screen.
  4149.  
  4150.      The Rationality Principle says that the user's behavior in
  4151. typing, mousing, and so on, can be explained by considering the
  4152. tasks required to achieve the goal, the operators available to
  4153. carry out the tasks, and the limitations on the user's knowledge,
  4154. observations, and processing capacity.  This sounds like the
  4155. typical user of a computer program must spend a good deal of time
  4156. scratching his head and wondering what to do next.  In fact, one
  4157. of Card and Moran's key results is that this is NOT what takes place.
  4158.  
  4159.      What happens, in fact, is that the trained user strikes a sort
  4160. of "modus vivendi" with his tool and adopts a set of repetitive,
  4161. trained behavior patterns as the best way to get the job done.
  4162. He may go so far as to ignore some functions of the program in
  4163. order to set up a reliable pattern.  What we are looking for is a
  4164. way of measuring and predicting the "quality" of this trained
  4165. behavior.  Since using computers is a human endeavor, we should
  4166. consider not only the speed with which the task is completed, but
  4167. the degree of annoyance or pleasure associated with the process.
  4168.  
  4169.      Card and Moran constructed a series of behavioral models which
  4170. they called GOMS models, for Goals-Operators-Methods-Selection.
  4171. These models suggested that in the training process the user
  4172. learned to combine the basic operators in sequences (chunks!)
  4173. which then became methods for reaching the goals.  Then these
  4174. first level methods might be combined again into second level
  4175. methods, and so forth, as the learning progressed.
  4176.  
  4177.      The GOMS models were tested in a lengthy series of trials
  4178. at Xerox PARC using a variety of word processing software.  (Among
  4179. the subjects of these experiments were the inventors of
  4180. the windowing methods used in GEM!)  The results were again
  4181. surprising: the level of detail in the models was really unimportant!
  4182.  
  4183.      It turned out to be sufficient to merely count up the number
  4184. of keystrokes, mouse movements, and thought intervals required
  4185. by each task.  After summing up all of the tasks, any extra time
  4186. for the computer to respond, or the user to move his hands from
  4187. keyboard to mouse, or eyes from screen to printed page is added in.
  4188. This simplified version is called the Keystroke-Level Model.
  4189.  
  4190.      As an example of the Keystroke Model, consider the task of
  4191. changing a mistyped letter on the screen of a GEM word processor.
  4192. This might be broken down as follows: 
  4193.  
  4194. \begin{enumerate}
  4195.         \item find the letter on the screen;
  4196.         \item move hand to mouse;
  4197.         \item point to letter;
  4198.         \item click mouse button;
  4199.         \item move hand to keyboard;
  4200.         \item strike {\tt Delete} key;
  4201.         \item strike key for new character.
  4202. \end{enumerate}
  4203.  
  4204.      The sufficiency of the Keystroke Model is great news for our
  4205. attempt to design faster interfaces.  It says we can concentrate
  4206. our efforts on minimizing the number of total actions to be taken,
  4207. and making sure that each action is as fast as possible.  We have
  4208. already discussed some ways to speed up the mouse and keyboard
  4209. actions, so let's now consider how to speed up the thought intervals,
  4210. and cut the number of actions.
  4211.  
  4212.      One way to cut down "think time" is to make sure that the
  4213. capacity of short-term memory is not exceeded during the course of
  4214. a task.  For example, the fix-a-letter task described above required
  4215. the user to remember:
  4216.  
  4217. \begin{enumerate}
  4218.         \item his place in the overall job of typing the document;
  4219.         \item the task he is about to perform;
  4220.         \item where the bad character appeared, and
  4221.         \item what the new character was.
  4222. \end{enumerate}
  4223.  
  4224. When this total of items creeps toward seven, the user often loses his place
  4225. and commits errors.
  4226.  
  4227.      You can appreciate the ubiquity of this problem by considering
  4228. how many times you have made mistakes nesting parentheses,
  4229. or had to go back to count them, because too many things happened
  4230. while typing the line to remember the nesting levels. The moral is that
  4231. operations with long strings of operands should be avoided when
  4232. designing an interface.
  4233.  
  4234.      The single most important factor in making an interface
  4235. comfortable to use is increasing its predictability, and
  4236. decreasing the amount of indecision present at each step during
  4237. a task.  There is (inevitably) an Uncertainty Principle which
  4238. relates the number of choices at each step to the associated
  4239. time for thought:
  4240.  
  4241. \begin{equation}
  4242.      T = I \cdot \log_2 ( N + 1 )
  4243. \end{equation}
  4244.  
  4245.  where LOG2 is the binary logarithm function, N is the number of
  4246. equally probable choices, and I is a constant of approximately
  4247. 140 msec/bit.  When the alternates are not equally probable, the
  4248. function is more complex:
  4249.  
  4250. \begin{equation}
  4251.      T = I \cdot \sum_{i=1}^N P(i) \cdot \log_2 ( \frac{1}{P(i)+1} )
  4252. \end{equation}
  4253.  
  4254.  where the P(i) are the probabilities of each of the choices (which
  4255. must sum to one).  Those of you with some information theory
  4256. background will recognize this formula as the entropy of
  4257. the decision; we'll come back to that later.
  4258.  
  4259.      So what can we learn from this hash?  It turns out, as we might
  4260. expect, that we can decrease the decision time by making some
  4261. of the user's choices more probable than others.  We do that by
  4262. means of feedback cues from the interface.
  4263.  
  4264.      The importance of reliable, continuous meaningful feedback
  4265. cannot be emphasized enough.  It helps the beginner learn the system,
  4266. and its predictability makes the program comfortable for the expert.
  4267. Programs with no feedback, or unreliable cues, produce confusion,
  4268. dissonance, and frustration in the user.
  4269.  
  4270.      This principle is so important that I going to give several
  4271. examples from common GEM practice.  The Desktop provides several
  4272. instances.  When an object is selected and a menu drops down, only
  4273. those choices which are legal for the object are in black.  The
  4274. others are dimmed to grey, and are therefore removed from the
  4275. decision.  When a pick is made from the menu, the bar entry remains
  4276. black until the operation is complete, reassuring the user that
  4277. the correct choice was made.  In both the Desktop and the RCS,
  4278. items which are double-clicked open up with a "zoom box" from
  4279. the object, again showing that the right object was picked.
  4280.  
  4281.      Other techniques are useful when operator icons are exposed on
  4282. the screen.  When an object is picked, the legal operations might
  4283. be outlined, or the bad choices might be dimmed.  If the screen
  4284. flashing produced by this is objectionable, the legal icons can
  4285. be made mouse sensitive, so they will "light up" when the cursor
  4286. passes over - again showing the user which choices are legal.
  4287.  
  4288.      The desire for feedback is so strong that it should be provided
  4289. even while the computer is doing an operation on its own.  The hour
  4290. glass mouse form is a primitive example of this.  More sophisticated
  4291. are "progress indicators" such as animated thermometer bars,
  4292. clocks, or text displays of the processing steps.  The ST Desktop
  4293. provides examples in the Format and Disk Copy functions.  The purpose
  4294. of all of these is to reassure the user that the operation is
  4295. progressing normally.  Their lack can lead to amusing spectacles
  4296. such as secretaries leaning over to hear if their disk drives are
  4297. working!
  4298.  
  4299.      Another commonly overlooked feature is error prevention and
  4300. correction.  Card and Moran's results showed that in order to go
  4301. faster, people will tolerate error rates of up to 30% in their
  4302. work.  Any program which does not give a fast way to fix mistakes
  4303. will be frustrating indeed!
  4304.  
  4305.      The best way to cope with an error is to "make it didn't happen",
  4306. to quote a common child's phrase.  The same feedback methods
  4307. discussed above are also effective in preventing the user from
  4308. picking inappropriate combinations of objects and operations.
  4309. Replacement of numeric type-ins with sliders or other visual
  4310. controls eliminates the common "Range Error".  The use of radio
  4311. buttons prevents the user from picking incompatible options.
  4312. When such techniques are used consistently, the beginner also
  4313. gains confidence that he may explore the program without blundering
  4314. into errors.
  4315.  
  4316.      Once an error has occured, the best solution is to have an
  4317. "inverse operation" immediately available.  For instance, the way
  4318. to fix a bad character is to hit the backspace key.  If a line is
  4319. inadvertantly deleted, there should be a way to restore it.
  4320.  
  4321.      Sometimes the mechanics of providing true inverses are
  4322. impractical, or end up cluttering the interface themselves.  In
  4323. these cases, a global "Undo" command should be provided to
  4324. reverse the effect of the last operation, no matter what it was.
  4325.  
  4326. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4327. \subsection{Of modes and bandwidth}
  4328.  
  4329.   Now I am going to depart from
  4330. the Card, Newell and Moran thread of discussion to consider
  4331. how we can minimize the number of operations in a task by
  4332. altering the modes of the interface.  Although "no modes" has
  4333. been a watchword of Macintosh developers, the term may need
  4334. definition for Atarians.
  4335.  
  4336.      Simply stated, a mode exists any time you cannot get to
  4337. all of the capabilities of the program without taking some
  4338. intermediate step.  Familiar examples are old-style "menu-driven"
  4339. programs, in which user must make selections from a number of
  4340. nested menus in order to perform any operation.  The options
  4341. of any one menu are unavailable from the others.
  4342.  
  4343.      Recall that the user is trying to accomplish work in his
  4344. own problem space, by altering its states.  A mode in the
  4345. program adds additional states to the problem space, which he is
  4346. forced to consider in order to get the job done.  We might call
  4347. an interface which is completely modeless "transparent", because it
  4348. adds no states between the user and his work.  One of the best
  4349. examples of a transparent program is the 15-puzzle in the Macintosh
  4350. desk accessory set.  The problem space of rearranging the tiles
  4351. is identical between the program and a physical puzzle.
  4352.  
  4353.      Unfortunately, most programmers find themselves forced to
  4354. put modes of some sort into their programs.  These often arise
  4355. due to technological limitations, such as memory space, screen
  4356. "real estate", or performance limitations of peripherals.  The
  4357. question is how the modes can be made least offensive.
  4358.  
  4359.      I will make the general claim that the frustration which a
  4360. mode produces is directly proportional to the amount of the user's
  4361. bandwidth which it consumes.  In other words, we need to consider
  4362. how many keystrokes, mouse clicks, eye movements, and so on, are
  4363. going into manipulating the true problem states, and how many
  4364. are being absorbed by the modes of the program.  If the interface
  4365. is wasting a large amount of the user's effort, it will be perceived
  4366. as slow and annoying.
  4367.  
  4368.      Here we can consider again the hierarchy of goals and methods
  4369. which the user employs.  When the mode is low in the hierarchy,
  4370. and close to the user's "fingertips", it is encountered the most
  4371. frequently.  For instance, consider how frustrating it would be
  4372. to have to hit a function key before typing in each character!
  4373.  
  4374.      The "menu-driven" style of programs mentioned above are
  4375. almost as bad, since usually only one piece of information is
  4376. collected at each menu.  Such a program becomes a labyrinth of
  4377. states better suited to an adventure game!
  4378.  
  4379.      The least offensive modes are found at the higher, goal
  4380. related levels of the hierarchy.  The better they align with
  4381. changes in the state of the original problem, the more they
  4382. are tolerated.  For example, a word processing program might
  4383. have one screen layout for program editing, another for writing
  4384. letters, and yet another while printing the documents.  A
  4385. multi-function business package might have one set of menus for
  4386. the spreadsheet, another for a graphing module, and a third
  4387. for a database.
  4388.  
  4389.      In some cases the problem solved by the program has convenient
  4390. "fracture lines" which can be used to define the modes.  An
  4391. example in my own past is the RCS, where the editing of each
  4392. type of resource tree forms its own mode, with each of the modes
  4393. nested within the overall mode and problem of composing the
  4394. entire resource tree.
  4395.  
  4396. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4397. \subsection{To do is to be!}
  4398.  
  4399.   Any narrative description of user interface
  4400. is bound to be lacking.  There is no way text can convey the vibrancy
  4401. and tactile pleasure of a good interface, or the sullen boredom
  4402. of a bad one.  Therefore, I encourage you to experiment.  Get out
  4403. your favorite arcade game and see if you can spot some of the
  4404. elements I have described.  Dig into your slush pile for the most
  4405. annoying program you have ever seen, run it and see if you can see
  4406. mistakes.  How would you fix them?  Then... go do it to your own
  4407. program!
  4408.  
  4409. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4410. \newpage
  4411. \section{More User Psychology}
  4412.  
  4413. This chapter continues the discussion of user interface design. It begins
  4414. where we left off, with a further treatment of the mode problem, and
  4415. proceeds into topics such as visual grammar and layered interfaces.
  4416.  
  4417. \subsection{Modes Again}
  4418.  
  4419. If a program is modeless, it acts predictably, which turns out to be 
  4420. very important. On the other hand, a good definition for ``modes'' is hard 
  4421. to find. In the previous chapter I suggested that a mode exists when you cannot 
  4422. use all of the capabilities of the program without performing some 
  4423. intermediate step. If this is less than clear, here are two alternate 
  4424. definitions offering different views of the problem.
  4425.  
  4426. The "TWO USER TEST". Consider the following thought experiment: Imagine 
  4427. that your ST (and GEM) had two mice, two cursors, and two users. Could 
  4428. they both effectively use the program at the same time? If so, the 
  4429. application is modeless. If there are points where one user can be 
  4430. ``locked out'' by the actions of the other, then a mode exists at that 
  4431. point. Let's consider some examples of this test.
  4432.  
  4433. In any program which uses the GEM menu system, one user could stop the 
  4434. other by touching a menu hotspot and dropping a menu. This constitutes 
  4435. an inherent mode in the GEM architecture.
  4436.  
  4437. On the GEM Desktop, two users could open windows and view files without 
  4438. interference. However, as soon as one person tries to delete a file 
  4439. (assuming the verify option is on), the other is brought to a halt as a 
  4440. dialog appears. Thus, we have found a modal dialog.
  4441.  
  4442. In many "Paint-type" programs, such as MacPaint, PC Paint, and GEM 
  4443. Paint, two artists could co-exist quite well, utilizing the on-screen 
  4444. palette and tool selection. Of course, these programs also contain modal 
  4445. dialogs for such operations as file and brush shape selection. In 
  4446. contrast, consider the paint program DEGAS for the ST. Here, two artists 
  4447. could only work together as long as neither wanted to change tool or 
  4448. color. Then the display would have to be flipped to the selection 
  4449. screen, stopping the other user. This is a mode in the DEGAS interface.
  4450.  
  4451. (By the way, this test is not just academic. The grand-daddy of all 
  4452. mouse based systems, NLS, demonstrated by Doug Englebart in 1968, had 
  4453. two mice and two users, one of whom was physically remote. Cooperative 
  4454. techniques such as this are still largely unexplored and unexploited.)
  4455.  
  4456.  
  4457. \subsection{One Liner}
  4458.  
  4459. Here's a terse definition by Jef Raskin: A program is modeless if a 
  4460. given action has one and only one result. Again, let's run a few 
  4461. examples.
  4462.  
  4463. The menu dropdowns are clearly modal by this definition. Before the menu 
  4464. was activated, window control points could be activated with a click. 
  4465. However, when the dropdown is visible, a click action is interpreted as 
  4466. a menu selection or a dismissal of the dropdown. Similarly, dialogs are 
  4467. modal because the action of moving the mouse into the menu bar no longer 
  4468. causes the dropdown to appear.
  4469.  
  4470. I am typing this using the First Word editor program. It has a nice 
  4471. desktop level box full of characters where I can click to get symbols 
  4472. which the ST keyboard won't produce. However, if I invoke the find or 
  4473. replace string dialog, the click-in-the-box action doesn't work anymore. 
  4474. This is a mode in the First Word interface.
  4475.  
  4476. Finally, consider an "old style" menu program, the kind where you type 
  4477. in the number of the desired action from a list. Since the number "2" 
  4478. might mean "Insert the record" in one menu, and "Purge the file" in 
  4479. another, such a program is clearly modal by Raskin's definition.
  4480.  
  4481. These three definitions say almost the same thing, but from different 
  4482. viewpoints. Depending on the situation, one or the other may be more 
  4483. intuitive for you. The goal of this type of analysis is to root out 
  4484. unnecessary modes, and to make sure that those which remain only appear 
  4485. when requested by the user, offer some visual cue such as a rubber line 
  4486. or standard dialog box, and are used consistently throughout the 
  4487. application.
  4488.  
  4489.  
  4490. \subsection{Predictability Forever And Ever}
  4491.  
  4492. As Raskin's definition makes clear, when the modes go away, the 
  4493. interface becomes predictable. Predictability leads to the formation of 
  4494. habits of use. Habits reduce "think time" and become progressively 
  4495. faster due to the Power Law of Practice I have discussed. This 
  4496. is exactly what we want!
  4497.  
  4498. There is another benefit of predictability. A habit learned in one part 
  4499. of a program with a consistent interface can be transferred and used 
  4500. elsewhere in the application. If several programs share the same style 
  4501. of interface, the same habits can be used across a complete set of 
  4502. products. Learning time for the new functions becomes shorter, and the 
  4503. user is more likely to use the new feature.
  4504.  
  4505.  
  4506. \subsection{It's A Bogeyman!}
  4507.  
  4508. Most casual users are scared silly of computers and programs. (If you 
  4509. have any doubt, eavesdrop on a secretary with a new word processor, or 
  4510. the doctor's receptionist coping with an insurance data entry program.) 
  4511. In most cases, they have a right to be frightened. Even experienced 
  4512. programmers, prone to toss the manuals and hack away, know that moderate 
  4513. paranoia is the best way to deal with an unknown program. How must this 
  4514. feel to someone whose ability to perform (or lose) their job depends on 
  4515. an unpredictable (aha!) black box.
  4516.  
  4517. So here's another way in which predictability works. But to produce a 
  4518. truly fearless user, we need other qualities as well. One is robustness, 
  4519. meaning that the program will not crash given normal or even bizarre 
  4520. actions by the user. Another is feedback, which shuts off invalid 
  4521. options, reinforces correct actions, and gives reassurance that an 
  4522. operation is proceeding normally. Finally, we need forgiveness, in the 
  4523. form of inverse operations or Undo options, when the inevitable mistake 
  4524. is made.
  4525.  
  4526. The ultimate goal is make the program discoverable. This means the user 
  4527. should be able to safely "wing it" after a short session with the 
  4528. application and its interface. This practice ought to be considered the 
  4529. norm anyway, since the manual is always across the office or missing 
  4530. when an esoteric and half-forgotten feature is needed. If it is possible 
  4531. to muddle through such a situation by trial and error, without causing 
  4532. damage, the immediate problem will be solved, and the user will gain 
  4533. confidence.
  4534.  
  4535.  
  4536. \subsection{Good Grammar Or...}
  4537.  
  4538. So exactly what are these habits that are supposed to be so helpful? One 
  4539. of the most useful patterns is a consistent command grammar for the 
  4540. program. This may sound strange, since we have supposedly abandoned 
  4541. command line interfaces in the graphics world, but in fact, the same 
  4542. type of rules apply. For instance, in the world of \verb"A>" we might issue the 
  4543. command:
  4544.  
  4545. \begin{verbatim}
  4546.     copy a:foobar.txt b:
  4547. \end{verbatim}
  4548.  
  4549. By analogy to Englist grammar, this command contains a verb, \verb"copy", a 
  4550. file as subject: \verb"a:foobar.txt", and a location as an object: \verb"b:". The 
  4551. equivalent GEM Desktop operation is:
  4552.  
  4553. \begin{enumerate}
  4554. \item     Move mouse to {\tt foobar.txt} icon in {\tt a:} window
  4555. \item     Press mouse button
  4556. \item     Move mouse to {\tt b:} icon
  4557. \item     Release mouse button
  4558. \end{enumerate}
  4559.  
  4560. The operation can be described as a select-drag-drop sequence, with the 
  4561. select designating the subject file, the drag denoting the operation 
  4562. (copy), and the location of the drop showing the object. A grammar still 
  4563. exists, but its "terminal symbols" are composed of mouse actions 
  4564. interpreted in the context of the current screen display, rather than 
  4565. typed characters.
  4566.  
  4567. One useful way to analyze simple grammars, including those used as 
  4568. command languages, is to separate them into prefix, postfix, and infix 
  4569. forms. In a prefix grammer, the operation to be performed precedes its 
  4570. operands, that is, its subject(s) and object(s). The DOS copy command 
  4571. given above is an example of a prefix command. LISP is an example of a 
  4572. language which uses prefix specification for its commands.
  4573.  
  4574. Postfix grammars specify the action after all of the operands have been 
  4575. given. This command pattern is familiar to many as the way in which 
  4576. Hewlett-Packard calculators work. FORTH is an example of a language 
  4577. which uses a postfix grammar.
  4578.  
  4579. Infix notation places the verb, or operator, between its subject and 
  4580. object. Conventional algebraic notation is infix, as are most computer 
  4581. languages such as C or PASCAL. The example GEM command given above is 
  4582. also infix, since the selection of a subject file preceded the action, 
  4583. which was followed by the designation of an object.
  4584.  
  4585. The "standard" GEM command grammar, as used in the products produced by 
  4586. Digital Research, is in fact infix. This is not to say that GEM enforces 
  4587. such a convention, or that it is rigorously followed. However, when 
  4588. there is no pressing reason for a change, adoption of an infix command 
  4589. grammar will make your application feel most like others which users may 
  4590. have seen.
  4591.  
  4592. The general problem of specifying a graphic command language can be 
  4593. difficult, but much of the problem has already been handled on the ST. 
  4594. Part of the solution is by constraint: the input and output hardware of 
  4595. the ST are predefined, so most developers will not need to worry about 
  4596. choosing a pointing device or screen resolution. The other part of the 
  4597. standard solution is the GEM convention for mouse usage. I am going to 
  4598. review these rules, and then describe of the situations in which they 
  4599. have been bent, and finally some alternate approaches which may prove 
  4600. useful to some developers.
  4601.  
  4602. \subsection{Specifying A Subject}
  4603.  
  4604. There are really two sets of methods for designating what is to be 
  4605. affected by an operation. One set is used when distinct objects are to 
  4606. be affected. Examples are file and disk icons in the Desktop and trees 
  4607. in the RCS. Another set of designation methods is used when continuous 
  4608. material, such as text or bit images, is being handled.
  4609.  
  4610. When dealing with objects, a single mouse click (down and up) over the 
  4611. object selects it. The application should show that the selection has 
  4612. occurred by changing the appearance of the object. The most common 
  4613. methods are inverting the object, or drawing "handles" around it.
  4614.  
  4615. Many operations allow "plural", or multiple object, selections. The GEM 
  4616. convention is that a click on an object while the shift key is held down 
  4617. extends the selection by adding that object. If the shift-clicked object 
  4618. was already selected, it is deleted from the selection list.
  4619.  
  4620. Another way to select multiple objects is to use a "rubber box" to 
  4621. enclose them. This operation begins with drag on a part of the view 
  4622. where no object is present. The application then animates a rubber box 
  4623. on the screen as long as the mouse button is held down. When the button 
  4624. is released, all objects within the current extent of the box are 
  4625. selected. A shift-drag combination could be used to add the objects to 
  4626. an existing selection list.
  4627.  
  4628. Selecting part of a text or bit plane display is also done with a rubber 
  4629. box. Since there are no "objects" in the view, any mouse drag is 
  4630. interpreted as the beginning of a selection operation. In the simplest 
  4631. case, a bit plane, the rectangle within the box when the button is 
  4632. released is the selected extent.
  4633.  
  4634. When the underlying data has structure, such as words and lines of text, 
  4635. the display should reflect this fact during the selection operation. 
  4636. Typically, text selection is indicated by inversion of the characters 
  4637. rather than a rubber box. The selection extends along the starting line 
  4638. so long as the mouse stays within the line. If the mouse move off the 
  4639. starting text line, the implied selection is all characters between the 
  4640. starting character and the character currently under the mouse, which is 
  4641. not necessarily a rectangular area.
  4642.  
  4643. An extended "plural" selection may be supported in text editing. The use 
  4644. of the shift key is also conventional in this application.
  4645.  
  4646.  
  4647. \subsection{Action}
  4648.  
  4649. With the subject designated, the user can now choose an operation. In 
  4650. many cases, this will be picked from the menu, in which case the entire 
  4651. command is complete. Some menu selections will lead to dialogs, in which 
  4652. the interaction methods are regulated by the GEM form manager. When the 
  4653. command is completed, it is often helpful if the application leaves the 
  4654. objects (or areas) selected and ready for another operation. A single 
  4655. click away from any object is interpreted as cancelling the selections.
  4656.  
  4657. Many operations are indicated by gestures on the screen. Usually, this 
  4658. is some variant of a drag operation. The interpretation of the gesture 
  4659. may depend on the type and location of the selected subject, which part 
  4660. of it is under the mouse, and in what location the drag terminates.
  4661.  
  4662. "Handles" are small boxes or dot displayed around an object when it is 
  4663. selected. A drag beginning with the mouse on a handle is usually 
  4664. interpreted as a resizing operation, if this is appropriate. The 
  4665. pointing finger mouse form is displayed to indicate the operation in 
  4666. progress, and a rubber version of the object is animated on the screen 
  4667. to show the user the result if the button were released. In some cases, 
  4668. where an underlying "snap" grid exists, the animated object may change 
  4669. size in discrete steps.
  4670.  
  4671. Dragging a non-handle area of a selected object is usually interpreted 
  4672. as the beginning of a move function. In most applications, a move of a 
  4673. single object may be started without pre-selection. Simply beginning the 
  4674. drag on the object is taken to imply selection. The spread hand, or 
  4675. "grabber", mouse form is typically displayed during a drag operation.
  4676.  
  4677. Dragging may denote copying or movement, or more complex functions such 
  4678. as instantiation or generalization. The operation implied by movement on 
  4679. the screen will differ among applications, and often within the same 
  4680. application, depending on target location. This target is the recipient 
  4681. of the command's action, or its object, in an English grammar sense.
  4682.  
  4683. For example, a drag from window to window in the Desktop denotes a copy. 
  4684. On the other hand, dragging the same icon to the trashcan deletes it 
  4685. completely. Dragging an object from the RCS partbox to the editing view 
  4686. creates a new copy of that prototype object. Dragging the same object 
  4687. within the edit view simply changes its placement.
  4688.  
  4689. There are some mouse actions which are conventional "abbreviations". A 
  4690. double click on an object is interpreted as both a selection and an 
  4691. action. Usually, the double click action is the same as the Open entry 
  4692. in the "File" menu.
  4693.  
  4694. When the usual interpretation of a drag is movement, then shift-drag may 
  4695. be used as an enhanced varient implying copying. For instance, shift-
  4696. dragging an object within the RCS editing window makes a copy of the 
  4697. object and places it in the final location.
  4698.  
  4699. To return to the beginning of this discussion, the reason for adopting 
  4700. these conventional usages is to build an interface that promotes habits. 
  4701. Particularly, a standard grammar for giving commands helps answer the 
  4702. question "What comes next?". It breaks the user's actions into logical 
  4703. phrases, or chunks, which may be thought of a whole, rather than one 
  4704. action at a time.
  4705.  
  4706. \subsection{Different Folks, Different Strokes}
  4707.  
  4708. There are always exceptions to a rule, or so it seems. In this case, 
  4709. consistency of the interface grammar is sometimes traded off against 
  4710. consistency of metaphor, preservation of screen space, and "fast path" 
  4711. methods for experts.
  4712.  
  4713. One example is the use of "tools" in Paint and Draw programs. In such 
  4714. programs, an initial click is made on a tool icon, denoting the 
  4715. operation to be applied to all following selections. This is an prefix 
  4716. style of grammar, and stands in contrast to the usual method of 
  4717. selecting subject object(s) first. Because of this contrast, it is 
  4718. sometimes called "moding the cursor". (Try applying the tests above to 
  4719. be sure it really is a mode.)
  4720.  
  4721. In these cases, there are two reasons for accepting the nonstandard 
  4722. method. The first is consistency of metaphor. The "user model" portrayed 
  4723. in the programs is an artist's work table, with tools, palette, and so 
  4724. on. The cursor moding action is equivalent to picking up a working tool. 
  4725. The second reason is speed. In a Paint program, the "canvas" is often 
  4726. modified, and speed in creating or changing the bits is important. In 
  4727. more object oriented applications such as Desktop or RCS, the objects 
  4728. are more persistent. Speed is then more essential when adding or 
  4729. changing properties of the objects.
  4730.  
  4731. When command styles are mixed in this fashion, you must design very 
  4732. carefully to avoid conflicts or apparent side-effects in the command 
  4733. language. For example, in GEM Draw picking an action from the Edit menu 
  4734. cancels the current cursor mode without warning. Confusion from such 
  4735. side-effects may cancel out the benefits of the mixed grammar.
  4736.  
  4737. The subject of command further attention. While the novice approaching a 
  4738. program needs full feedback, a person who uses it day in and day out 
  4739. will learn the program, and want faster ways to get the job done, even 
  4740. if they are more arcane. The gives rise to a "layered" style of 
  4741. interface.
  4742.  
  4743. A layered interface is designed so that the visual grammar is obvious, 
  4744. as we have discussed. However, there are one or more sets of 
  4745. "accelerators" built into the program, which may be harder to find but 
  4746. faster to use. One example is condensed mouse actions such as the 
  4747. double-click. For instance, attempting to select a block of text which 
  4748. extends beyond a window is impossible using the basic metaphor. The 
  4749. novice will simply do the operation in pieces. A layered interface might 
  4750. put a less obvious Mark Begin and Mark End option in the menus. Another 
  4751. way is to take a drag which extends outside the window as a request to 
  4752. begin scrolling in that direction, while extending the current 
  4753. selection.
  4754.  
  4755. One of the most common and useful accelerator methods is function keys. 
  4756. Using this approach, single key equivalents to actions are listed in the 
  4757. menu. Striking this key when an object is selected will cause the action 
  4758. to occur. Note that this is most useful if some keyboard driven method 
  4759. of object selection, such as tabbing, is also available. Otherwise, the 
  4760. time switching from the mouse, used to select the object, to the 
  4761. keyboard for command input, may well cancel any advantage.
  4762.  
  4763. Finally, radical departures from the GEM metaphor may be useful when 
  4764. attempting to replicate the look of another system, or trying to meet 
  4765. severe constraints, such as display space. One example would be 
  4766. discarding the standard GEM menus in favor of "popup" menus which appear 
  4767. next to the current mouse position in response to a click on the second 
  4768. button. This method has the advantage of preserving the menu space at 
  4769. the top of the screen, and is potentially faster because the menu 
  4770. appears right next to the current mouse position. The drawbacks are lack 
  4771. of a visual cue for naive users trying to find the commands, and the 
  4772. need for custom coding to build the popups.
  4773.  
  4774.  
  4775. \subsection{More To Come}
  4776.  
  4777. We have reached the end of the second sermon on user interface. In a 
  4778. future chapter, I will look at "higher level" topics relating to the 
  4779. design of the application's user metaphor. These include issues of 
  4780. object orientation, direct manipulation, and the construction of 
  4781. microworlds. In the meantime, several of the more practical columns will 
  4782. present implementions of techniques such as accelarator keys and popup 
  4783. menus which I have discussed this time.
  4784.  
  4785. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4786. \subsection{References}
  4787.  
  4788.   Stuart K.~Card, Thomas P.~Moran, and Allen Newell:
  4789.  {\em The Psychology of Human-Computer Interaction}, Lawrence
  4790. Erlbaum Associates, Hillsdale, New Jersey, 1983.  (Fundamental
  4791. and indispensible.  The volume of experimental results make it
  4792. weighty.  The Good Parts are at the beginning and end.)
  4793.  
  4794.      {\em Macintosh User Interface Guidelines}, in Inside Macintosh,
  4795. Apple Computer, Inc., 1984.  (Yes, Atarians, we have something to
  4796. learn here.  Though not everything "translates", this is a fine
  4797. piece of principled design work.  Read and appreciate.)
  4798.  
  4799.      James D.~Foley, Victor L.~Wallace, and Peggy Chan,
  4800. {\em The Human Factors of Computer Graphics Interaction Techniques},
  4801. IEEE Computer Graphics (CG \& A), November 1984, pp. 13--48.
  4802. (A good overview, including higher level topics which I have
  4803. postponed to a upcoming later section.  Excellent bibliography.)
  4804.  
  4805.      J.~D.~Foley and A.~Van Dam,
  4806. {\em Fundamentals of Interactive Computer Graphics},
  4807. Addison Wesley, 1984, Chapters 5 and 6.
  4808. (If you can't get the article above, read this.  If you are designing
  4809. graphics apps, buy the whole book!  Staggering bibliography.)
  4810.  
  4811.      Ben Schneidermann, {\em Direct Manipulation: A Step Beyond
  4812. Programming Languages}, IEEE Computer, August 1983, pp. 57--69.
  4813. (What do Pacman and Visicalc have in common?  Schneidermann's
  4814. analysis is vital to creating hot interfaces.)
  4815.  
  4816.  
  4817. \newpage
  4818.  
  4819. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4820. \section{GEM Events and Program Structure}
  4821.  
  4822.      So I fibbed a little.  This chapter of ST Professional GEM started
  4823. out to be another discussion of interface issues.  But, as Tolkien
  4824. once said, the tale grew in the telling, and this is now the first
  4825. of  a series of three articles.   This part will discuss AES event
  4826. handling  and  its implications for GEM  program  structure.   The
  4827. following  will contain a "home brew" dialog handler  with
  4828. some  new  features,  and  will,  finally,  take up  the
  4829. discussion  of  interface design,  using the dialog handler as  an
  4830. example. 
  4831.  
  4832. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4833. \subsection{All for one, and one for all}
  4834.  
  4835.   A quick inspection of the AES
  4836. documents  shows that there are five routines devoted  to  waiting
  4837. for individual types of events, and one routine, \verb"evnt_multi", which
  4838. is  used  when more than one type is desired.   This article  will
  4839. discuss  ONLY \verb"evnt_multi" for two reasons.   First,  it is the most
  4840. frequently used of the routines.   Second, waiting for one type of
  4841. event is a bad practice.   Any event call turns the system over to
  4842. the AES and suspends the application and its interaction with  the
  4843. user.   In  such  cases,  some  "escape clause",  such as a timer,
  4844. should be inserted to revive the program and prompt the user if no
  4845. event  is  forthcoming.   Otherwise,  the  application may end  up
  4846. apparently  (or  actually)  hung,  with a  resulting  reboot,  and
  4847. probably a very annoyed user.
  4848.  
  4849. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4850. \subsubsection{Starting ahead}
  4851.  
  4852. One  possible type of event is a  message.
  4853. Messages  are usually sent to the application by the AES,  and are
  4854. associated  with  windows or the menu.   We have already
  4855. discussed such messages:
  4856. we considered  window  messages,  and we   handled  menu
  4857. messages.  You may want to review these topics before proceeding.
  4858.  
  4859.      The actual \verb"evnt_multi" call is a horrendous thing:
  4860.  
  4861. \begin{verbatim}
  4862.      ev_which = evnt_multi(ev_flags,
  4863.                btn_clicks, btn_mask, btn_state,
  4864.                r1_flags, r1_x, r1_y, r1_w, r1_h,
  4865.                r2_flags, r2_x, r2_y, r2_w, r2_h,
  4866.                &msg_buff,
  4867.                time_lo, time_hi,
  4868.                &mx, &my, &btn, &kbd, &char, &clicks);
  4869. \end{verbatim}
  4870.  
  4871. Each  of  the lines in the call relate to a different  event,  and
  4872. they  will be discussed in the order in which they  appear.
  4873.  
  4874.      Note  that a call with this number of parameters causes  some
  4875. overhead  due  to stacking and retrieval of the values.   In  most
  4876. cases,  this  should be of little concern on a machine as fast  as
  4877. the ST.   However, where throughput is a concern, such as in close
  4878. tracking  of the mouse cursor,  you may want to write a customized
  4879. binding  for \verb"evnt_multi" which dispenses with the  parameter  list.
  4880. This  can  be accomplished by maintaining the values in  a  static
  4881. array  and moving them as a block into the binding  arrays  \verb"int_in"
  4882. (for all values but \verb"&msg_buff"), and \verb"addr_in" (for \verb"&msg_buff").  Note
  4883. that  you  may {\em not}\/ simply leave the values in \verb"int_in";  other  AES
  4884. bindings reuse this space.
  4885.  
  4886.      {\tt ev\_flags}  and {\tt ev\_which} are both 16-bit integers  composed  of
  4887. flag bits.  Bits set in {\tt ev\_flags}\/ determine which event(s) the call
  4888. will  wait  for;  those  set in {\tt ev\_which}\/  indicate  what  event(s)
  4889. actually occurred.   Both use the following flag bit mnemonics and
  4890. functions:
  4891.  
  4892. \vskip.5cm
  4893. \begin{center}
  4894. \begin{tabular}{c|l}
  4895.      0x0001 & {\tt MU\_KEYBD} --- Keyboard input\\
  4896.      0x0002 & {\tt MU\_BUTTON} --- Mouse button(s)\\
  4897.      0x0004 & {\tt MU\_M1} --- Mouse rectangle \#1\\
  4898.      0x0008 & {\tt MU\_M2} --- Mouse rectangle \#2\\
  4899.      0x0010 & {\tt MU\_MESAG} --- AES message\\
  4900.      0x0020 & {\tt MU\_TIMER} --- Timer\\
  4901. \end{tabular}
  4902. \end{center}
  4903. \vskip.5cm
  4904.  
  4905. The  appropriate mnemonics are ORed together to create the  proper
  4906. {\tt ev\_flags}\/ value.
  4907.  
  4908.      There  is  one  common pitfall here.   Notice  that  multiple
  4909. events  may  be reported from one \verb"evnt_multi".   Event  merging  is
  4910. performed  by the AES in order to save space on the  application's
  4911. event queue.   If events have been merged,  more than one bit will
  4912. be  set in the {\tt ev\_which}\/ word.   Your application must check ALL of
  4913. the  bits  before  returning to a new  {\tt evnt\_multi}\/  call.   If  you
  4914. don't do this, some events may be effectively lost.
  4915.  
  4916.      The  first event to be considered is the mouse button.   This
  4917. is probably the most difficult event to understand and use.
  4918.  
  4919.      The  parameter  {\tt btn\_clicks} tells GEM the  maximum  number  of
  4920. clicks which you are interested in seeing.   This value is usually
  4921. two,  if your program uses the double-click method, or one if only
  4922. single  clicks  are used.   The AES returns the number  of  clicks
  4923. which caused the event through {\tt \&clicks}, which must be a pointer to
  4924. a word.
  4925.  
  4926.      GEM determines the number of clicks by the following  method.
  4927. When the first button-down is detected, a time delay is begun.  If
  4928. another  complete button-up,  button-down cycle is detected before
  4929. the time expires,  then the result is a double click.   Otherwise,
  4930. the  event is a single click.    Note that the final state of  the
  4931. buttons  is  returned via {\tt \&btn},  as described below.   By checking
  4932. this  final state,  you may determine whether a single click event
  4933. ended with the button up (a full click),  or with the button still
  4934. down  (which  may  be  interpreted as  the  beginning  of  a  drag
  4935. operation).   Double clicking is meaningless,  and not checked, if
  4936. the \verb"evnt_multi" is waiting on more than one button (see below).
  4937.  
  4938.      The double-click detection delay is variable,  and may be set
  4939. by your program using the call
  4940.  
  4941. \begin{verbatim}
  4942.      ev_dspeed = ev_dclick(ev_dnew, ev_dfunc);
  4943. \end{verbatim}
  4944.  
  4945. {\tt ev\_dfunc}\/  is a flag which determines the purpose of the call.   If
  4946. it  is  zero,  the  current  double click  speed  is  returned  in
  4947. {\tt ev\_dspeed}\/.   If {\tt ev\_dfunc}\/ is non-zero, then {\tt ev\_dnew}\/
  4948. becomes the new double-click   speed. Both {\tt ev\_dspeed}\/  and 
  4949. {\tt ev\_dnew}\/  are  words containing  a {\tt magic number}\/ between
  4950. zero and four.   Zero is  the
  4951. slowest  (i.e.,  longest)  double-click,  and four is the fastest.
  4952. (These  correspond  to  the  slow-fast  range  in  the   Desktop's
  4953. Preferences  dialog.)  In general,  you should not reset the click
  4954. speed  unless  specifically requested,  because such a change  can
  4955. throw off the user's timing and destroy the hand/eye  coordination
  4956. involved in using the mouse.
  4957.  
  4958.      GEM  was  originally designed to work with  a  single  button
  4959. input device.   This allows GEM applications to function well with
  4960. devices such as light pens and digitizing tablets.   However, some
  4961. features are available for dealing with multi-button mice like the
  4962. ST's.
  4963.  
  4964.      The  \verb"evnt_multi" parameters {\tt btn\_mask}\/ and {\tt btn\_state}\/  are  words
  4965. containing  flag bits corresponding to buttons.   The lowest order
  4966. bit corresponds to the left-most button,  and so on.  A bit is set
  4967. in  the  {\tt btn\_mask}\/ parameter if the AES is to  watch  a  particular
  4968. button.   The  corresponding bit in {\tt btn\_state}\/ is set to the  value
  4969. for  which  the program is waiting.   The word returned  via  {\tt \&btn}\/
  4970. uses  the  same  bit system to show the state of  the  buttons  at
  4971. completion.   It  is  important to notice that all of  the  target
  4972. states in {\tt btn\_state}\/ must occur {\em simultaneously}\/ for the event to  be
  4973. triggered.
  4974.  
  4975.      Note the limiting nature of this last statement.  It prevents
  4976. a  program from waiting for {\em either}\/ the left or right button to  be
  4977. pressed.  Instead, it must wait for {\em both}\/ to be pressed or to
  4978. be released, which is a
  4979. difficult  operation  at best.   As a result,  many people thought
  4980. the standard  mouse
  4981. button  procedure is practically useless if you want to take  full
  4982. advantage  of  both buttons on the ST mouse. 
  4983.  
  4984.      Fortunately there is a way out. If the upper byte of  {\tt btn\_clicks}
  4985. is set to one (by adding 256 to {\tt btn\_clicks}) the mouse event AES waits
  4986. for can be negated. So instead of waiting for "both mouse buttons released"
  4987. AES will wait for "NOT both mouse buttons released" which is actually
  4988. "one of the mouse buttons pressed". By reading  {\tt \&btn} we can then
  4989. easily determine which button was pressed. So setting  {\tt btn\_clicks})
  4990. to 256+2,  {\tt btn\_mask}) to 3 and  {\tt btn\_state}) to 0 will do the
  4991. trick!
  4992.  
  4993. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4994. \subsubsection{Mouse Rectangles}
  4995.  
  4996. One of GEM's nicer features is its ability
  4997. to watch the mouse pointer's position for you, and report an event
  4998. only  when it enters or departs a given screen region.   Since you
  4999. don't  have to track the mouse pixel by pixel,  this eliminates  a
  5000. lot  of application overhead.   The \verb"evnt_multi" call gives you  the
  5001. ability  to  specify one or two rectangular areas  which  will  be
  5002. watched.   An event can be generated either when the mouse pointer
  5003. enters the rectangle,  or when it leaves the rectangle.  The "r1\_"
  5004. series  of  parameters specifies one of the  rectangles,  and  the
  5005. "r2\_" series specifies the other, as follows:
  5006.  
  5007. \vskip.5cm
  5008. \begin{center}
  5009. \begin{tabular}{r|l}
  5010.      r1\_flag, r2\_flag & zero if waiting to enter rectangle,\\
  5011.                         & one if waiting to leave rectangle\\
  5012.      r1\_x, r2\_x & upper left X raster coordinate of wait rectangle\\
  5013.      r1\_y, r2\_y & upper left Y raster coordinate of wait rectangle\\
  5014.      r1\_w, r2\_w & width of wait rectangle in pixels\\
  5015.      r1\_h, r2\_h & height of wait rectangle in pixels
  5016. \end{tabular}
  5017. \end{center}
  5018. \vskip.5cm
  5019.  
  5020. Each  rectangle  wait will only be active if its  associated  flag
  5021. (\verb"MU_M1" or \verb"MU_M2") was set in {\tt ev\_flags}\/.
  5022.  
  5023.      There  are two common uses of rectangle waits.   The first is
  5024. used when creating mouse-sensitive regions on the screen.   Mouse-
  5025. sensitive regions, also called "hot spots", are objects which show
  5026. a  visual effect,  such as inversion or outlining,  when the mouse
  5027. cursor  moves  over them.   The items in a menu dropdown,  or  the
  5028. inversion  of  Desktop icons during a drag operation,  are  common
  5029. examples.
  5030.  
  5031.         Hot spots are commonly created by grouping  the  sensitive
  5032. objects  into  one  or  two areas,  and then setting  up  a  mouse
  5033. rectangle  wait  for  entering  the  area.    When  the  event  is
  5034. generated,  the  {\tt \&mx}  and {\tt \&my} returns may be examined to find  the
  5035. true  mouse coordinates,  and \verb"objc_find" or some other search  will
  5036. determine  the affected object.   The object is then  highlighted,
  5037. and  a new wait for exiting the object rectangle is  posted.
  5038.  
  5039.      The  second common use of rectangle waits is in  animating  a
  5040. drag operation.  In many cases, you can use standard AES animation
  5041. routines such as \verb"graf_dragbox" or \verb"graf_rubberbox".   In other cases,
  5042. you  may  want  a figure other than a simple  box,  or  desire  to
  5043. combine   waits  for  other  conditions  such  as  keystrokes   or
  5044. collision with hotspots.  Then you will need to implement the drag
  5045. operation  yourself,  using  the  mouse rectangles  to  track  the
  5046. cursor.
  5047.  
  5048.      If you want to track the cursor closely, simply wait for exit
  5049. on a one pixel rectangle at the current position,  and perform the
  5050. animation routine at each event.  If the drag operation only works
  5051. on a grid,  such as character positions,  you can specify a larger
  5052. wait  rectangle and only update the display when a legal  boundary
  5053. is crossed.
  5054.  
  5055. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5056. \subsubsection{Messages}
  5057.  
  5058. The  {\tt \&msg\_buff}\/ parameter of \verb"evnt_multi" gives  the
  5059. address  of a 16 byte buffer to receive an AES message.   As noted
  5060. above,  I have discussed standard AES messages elsewhere. The last
  5061. column  also mentioned that messages may be used to  simulate  co-
  5062. routines  within  a single GEM program.
  5063.  
  5064.      A  further possibility which bears examination is the use  of
  5065. messages  to coordinate the activities of multiple  programs.   In
  5066. single-tasking  GEM,  at least one of these programs would have to
  5067. be  a  desk accessory.   In any such use of the GEM messages,  you
  5068. should pay careful attention to the possibility of overloading the
  5069. queue.   Only  eight  slots are provided per task,  and  messages,
  5070. unlike events, cannot be merged by the AES.
  5071.  
  5072. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5073. \subsubsection{Timer}
  5074.  
  5075.    The  timer event gives you a way of pacing action on
  5076. the  screen,  clocking out messages,  or providing a time-out exit
  5077. for   an  operation.   \verb"Evnt_multi"  has  two  16-bit  timer  input
  5078. parameters,  {\tt time\_hi}\/  and  {\tt time\_lo}\/,  which are the top and  bottom
  5079. halves,  respectively,  of  a  32-bit millisecond count.   However,
  5080. this documented time resolution must be taken with a grain of salt
  5081. on the ST, considering that its internal clock frequency is 200Hz!
  5082.  
  5083.      The  timer  event is also extremely useful  for  polling  the
  5084. event  queue.   A  "poll"  tests the queue  for  completed  events
  5085. without going into a wait state if none are present.  In GEM, this
  5086. is   done  by  generating  a  null  event  which   always   occurs
  5087. immediately.  A timer count of zero will do just that.
  5088.  
  5089.      Therefore,  you  can poll for any set of events by specifying
  5090. them  in  the \verb"evnt_multi" parameters.   A zero timer wait  is  then
  5091. added to ensure immediate completion.   Upon return,  if any event
  5092. bit(s) {\em other}\/ than \verb"MU_TIMER" are set,  a significant event was found
  5093. on the queue.  If only \verb"MU_TIMER" is set, the poll failed to find an
  5094. event.
  5095.  
  5096. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5097. \subsubsection{Keyboard}
  5098.  
  5099.    There  are  no input parameters for the  keyboard
  5100. event.   The  character  which  is read is returned  as  a  16-bit
  5101. quantity through the {\tt \&char} parameter.  For historical reasons, the
  5102. codes  which  are returned are compatible with the IBM  PC's  BIOS
  5103. level scan codes.  You can find this character table in Appendix D
  5104. of  the  GEM VDI manual.   In general,  the high byte need only be
  5105. considered  if  the lower byte is zero.   If the low byte is  non-
  5106. zero, it is a valid ASCII character.
  5107.  
  5108.      \verb"evnt_multi"  also returns the status of several modifier  keys
  5109. through  the {\tt \&kbd} parameter.   This word contains four significant
  5110. bits as follows:
  5111.  
  5112. \vskip.5cm
  5113. \begin{center}
  5114. \begin{tabular}{c|l}
  5115.         0x0001 & Right hand shift key\\
  5116.         0x0002 & Left hand shift key\\
  5117.         0x0004 & Control key\\
  5118.         0x0008 & ALT key\\
  5119. \end{tabular}
  5120. \end{center}
  5121. \vskip.5cm
  5122.  
  5123. If  a  bit  is  one,  the key was depressed  when  the  event  was
  5124. generated.   Otherwise,  the key was up.  Since the state of these
  5125. keys  is already taken into account in generating the  {\tt \&char}\/  scan
  5126. code,  the  {\tt \&kbd}\/ word is most useful when creating enhanced  mouse
  5127. functions, such as shift-click or control-drag.
  5128.  
  5129. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5130. \subsubsection{Random notes on events}
  5131.  
  5132.    Although the {\tt \&mx},  {\tt \&my},  {\tt \&btn},  and
  5133. {\tt \&kbd}\/ returns are nominally associated with particular event types,
  5134. they are valid on any return from \verb"evnt_multi", and reflect the last
  5135. event  which was merged into that return by the AES.  If you  want
  5136. more  current values,  you may use \verb"graf_mkstate" to resample  them.
  5137. Whichever method you choose, be consistent within the application,
  5138. since  the point of sampling has an effect on mouse  and  keyboard
  5139. timing.
  5140.  
  5141.      Although  this and preceding chapters have been  presented  in
  5142. terms of a GEM application,  the event system has many interesting
  5143. implications  for desk accessories.   Since the AES scheduler uses
  5144. non-preemptive  dispatching,  accessories  have an event  priority
  5145. effectively  equal  to  the main  application.   Though  "typical"
  5146. accessories  wait  only for \verb"AC_OPEN" or \verb"AC_CLOSE" messages  when  in
  5147. their  quiescent state,  this is not a requirement of the  system.
  5148. Timer  and  other events may also be requested  by  an  accessory.
  5149. (Indeed,  there  is  no  absolute requirement  that  an  accessory
  5150. advertise  its presence with a \verb"menu_register" call.)  The  aspiring
  5151. GEM hacker might consider how these facts could be used to  create
  5152. accessories  similar  to  "BUGS" on the Mac,  or  to  the  "Crabs"
  5153. program  described  in  the September,  1985 issue  of  Scientific
  5154. American.
  5155.  
  5156. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5157. \subsubsection{Events and GEM Program Structure}
  5158.  
  5159.  Although the  \verb"evnt_multi"
  5160. call  might seem to be a small part of the entire GEM system,  its
  5161. usage has deep implications for the structure of any  application.
  5162. It is generally true that each use of \verb"evnt_multi" corresponds to  a
  5163. mode  in  the  program.   For instance,  \verb"form_do" contains its  own
  5164. \verb"evnt_multi",  and its invocation creates a moded dialog.  While the
  5165. dialog  is in progress,  other features such as windows and  menus
  5166. are unusable.  The \verb"graf_dragbox", \verb"graf_rubberbox", and \verb"graf_slidebox"
  5167. routines also contain \verb"evnt_multi" calls.   They create a mode which
  5168. is sometimes called "spring-loaded",  since the mode vanishes when
  5169. some continuing condition (a depressed mouse button) is removed.
  5170.  
  5171.      In consequence,  a well-designed,  non-modal GEM program will
  5172. contain only one explicit \verb"evnt_multi" call.  This call is part of a
  5173. top-level  loop  which  decodes events as they  are  received  and
  5174. dispatches  control  to  the appropriate  handling  routine.   The
  5175. dispatcher  must  always  distinguish  between  event  types.   In
  5176. programs  where  multiple windows are used,  it may also  need  to
  5177. determine which local data structure is associated with the active
  5178. window.
  5179.  
  5180.      This  construction  is  sometimes  called  a  "push"  program
  5181. structure,  because  it  allows the user to drive the  application
  5182. by generating events in any order.  This contrasts with the "pull"
  5183. structure of traditional command line or menu programs,  where the
  5184. application is in control and demands input at each step before it
  5185. proceeds.    "Push"  structure  promotes  consistent  use  of  the
  5186. user interface and a feeling of control on the part of the user.
  5187.  
  5188.  
  5189. \newpage
  5190.  
  5191. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5192. \section{A new Form Manager}
  5193.  
  5194.      This  is  the first chapter
  5195. devoted to explaining a large piece of code.  This article is also
  5196. the  second  in a series of three concerning  GEM  user  interface
  5197. techniques.   The  code is an alternate form (dialog) manager  for
  5198. GEM.   It  is listed as {\tt GEMCL13.C}.
  5199.  
  5200.      What  is  unique  about this version  of  the  form  manager?
  5201. First,  it  implements  all of the functions of the  standard  GEM
  5202. \verb"form_do"  routine,  as  well as adding a "hot spots" feature  which
  5203. causes  selectable  objects to become mouse-sensitive,  just  like
  5204. the   entries  in  menu  dropdowns.    The  second  (and  obvious)
  5205. difference  is that this form manager is provided in  source  code
  5206. form.   This  gives you the freedom to examine it and change it to
  5207. suit your own needs.
  5208.  
  5209.      I  have  several  purposes in presenting this  code.   It  is
  5210. intended   as  an  example  of  GEM  program  structure,   and  an
  5211. application  of  some  of  the  techniques  presented  in  earlier
  5212. columns.   It is also relevant to the continuing thread discussing
  5213. the necessity of feedback when constructing a user interface.
  5214.  
  5215. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5216. \subsection{On  with  the show}
  5217.  
  5218.    Taking your listing in hand,  you  will
  5219. quickly notice two things.   First, this program uses the infamous
  5220. portability macros,  so that it may be used with Intel versions of
  5221. GEM.  Second, the routines are arranged "bottom up", with the main
  5222. at the end,  and subroutines going toward the beginning.  (This is
  5223. a carry-over from my days with ALGOL and PASCAL.)  You should  now
  5224. turn to the \verb"form_do" entry point near the end of the code.
  5225.  
  5226.      One change has been made in the standard calling sequence for
  5227. \verb"form_do".   The  starting  edit field is now a pointer to a  value,
  5228. rather  than  the value itself.   The new \verb"form_do"  overwrites  the
  5229. initial value with the number of the object being edited when  the
  5230. dialog  terminated.   Using  this  information,  your program  can
  5231. restore the situation when the dialog is next called.   As before,
  5232. if there is NO editable field, the initial value should be zero.
  5233.  
  5234.      There are several local variables which maintain vital  state
  5235. information during the dialog interaction.  \verb"Edit_obj" is the number
  5236. of  the editable object currently receiving keystrokes.   \verb"Next_obj"
  5237. is  set when the mouse is clicked over an object.   If the  object
  5238. happens to be editable,  \verb"next_obj" becomes the new \verb"edit_obj".
  5239.  
  5240.      Three  variables are associated with the "hot-spot"  feature.
  5241. If \verb"hot_mode" is set to \verb"M1_ENTER", then the mouse is outside the area
  5242. of the dialog.   If it equals \verb"M1_EXIT", then the mouse is currently
  5243. in the dialog.   If it is in the dialog, \verb"hot_obj" indicates whether
  5244. there is an active "hot" object.   If its value is NIL (-1),  then
  5245. there is no active object.   Otherwise,  it is equal to the number
  5246. of the object which is currently "hot",  that is,  inverted on the
  5247. screen.   Finally, \verb"hot_rect" is the current wait rectangle.  If the
  5248. mouse is outside of the window, then the wait rectangle equals the
  5249. dialog's  ROOT.   If there is a current hot object,  then \verb"hot_rect"
  5250. equals  that  object's screen rectangle.   If the mouse is in  the
  5251. dialog,  but  not  within  a hot object,  then the wait  rectangle
  5252. defines  the  area within which no further  collision  checks  are
  5253. necessary.   This  is  arrived at through an  algorithm  explained
  5254. below.
  5255.  
  5256.      \verb"Form_do's" initialization code sets up the hot-spot  variables
  5257. to  trigger  if  the mouse is within the  dialog.   It  also  sets
  5258. starting  values  for \verb"edit_obj" and \verb"next_obj" which will  cause  the
  5259. edit startup code to be activated.
  5260.  
  5261.      The main portion of \verb"form_do" is a loop, exhibiting the type of
  5262. event  driven  structure  discussed in the  last  column.   Before
  5263. entering the \verb"evnt_multi" wait,  the status of \verb"next_obj" and \verb"edit_obj"
  5264. are  checked  to  see if a new object should  be  initialized  for
  5265. editing.   If  so,  \verb"objc_edit"  is called with the \verb"EDINIT"  function
  5266. code.   NOTE:  the \verb"objc_edit" calling sequence used in this program
  5267. differs from the one given in the AES manual,  which is incorrect!
  5268. You  should check the bindings you are using to be sure they  will
  5269. work with this code, and modify as necessary.
  5270.  
  5271.      The \verb"evnt_multi" is set up to wait for a mouse click (single or
  5272. double),  for  a  keyboard  input,  or  for the mouse  to  make  a
  5273. "significant"  movement,  as  discussed above.   Notice that since
  5274. \verb"form_do" is used as a subroutine, it does not handle messages which
  5275. are  normally  processed  by the main loop  of  your  application.
  5276. Notice that this creates a mode,  and that this routine as written
  5277. handles modal dialogs.   You could,  however, use this code as the
  5278. basis for a non-modal dialog handler by drawing the dialog  within
  5279. a  window,  and  combining the main loop of \verb"form_do" with the  main
  5280. loop  of your application.   (This possibility may be examined  in
  5281. the future.   In the meantime,  it is left as an exercise for
  5282. the reader.)
  5283.  
  5284.      The  event  bit vector is returned to the  variable  "which".
  5285. Since events are not mutually exclusive,  each possible event type
  5286. must be examined in turn before returning to the \verb"evnt_multi"  call.
  5287. The form manager's event handling routines are \verb"form_hot", for mouse
  5288. rectangle event, \verb"form_keybd", for character input, and \verb"form_button",
  5289. for  mouse  clicks.   \verb"Form_keybd"  and \verb"form_button" are  allowed  to
  5290. terminate  the  dialog by returning a value of false to  the  loop
  5291. control variable "cont".   If termination is imminent, or the user
  5292. has  clicked  on a new editable object,  \verb"objc_edit" is called  with
  5293. \verb"EDEND"  to remove the cursor from the old object.   The normal flow
  5294. of control then returns to edit setup and \verb"evnt_multi".
  5295.  
  5296.      A few cleanup actions are performed upon termination.  If the
  5297. terminating  object  (stored in \verb"next_obj") is not the same  as  the
  5298. \verb"hot_obj", then a race condition has occured and the hot object must
  5299. be cleared with \verb"objc_toggle" before exiting.   After this test, the
  5300. final  \verb"edit_obj"  value is passed back via the parameter,  and  the
  5301. terminating object is returned as the function value.
  5302.  
  5303. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5304. \subsection{Relaxen und Watchen das Blinkenlichten}
  5305.  
  5306. \verb"form_hot" is
  5307. responsible  for  maintaining on-screen hot-spots,  and  correctly
  5308. updating  the  internal hot-spot variables.   It is about  halfway
  5309. through the listing.
  5310.  
  5311.      The first action in \verb"form_hot" is to determine if the mouse has
  5312. just exited an object which is hot.  In this case, \verb"objc_toggle" is
  5313. called to unhighlight the object and reset the \verb"SELECTED" flag.
  5314.  
  5315.      The current mouse position is passed to \verb"form_hot" by  \verb"form_do".
  5316. It  is checked against the root rectangle of the dialog to see  if
  5317. the mouse is inside the dialog.  If not, the program must wait for
  5318. it  to re-enter,  so \verb"form_hot" sets the rectangle and waiting  mode
  5319. accordingly, and returns NIL as the new \verb"hot_obj".
  5320.  
  5321.      When the mouse is within the dialog, a regular \verb"objc_find" call
  5322. determines  the object at which it is pointing.   For an object to
  5323. be  mouse-sensitive,  it must be \verb"SELECTABLE" and not \verb"DISABLED".   If
  5324. the  found object meets these tests,  the mouse will "hover"  over
  5325. the  object,  waiting  to leave its screen rectangle.   Since  the
  5326. object might already be \verb"SELECTED" (and hence drawn reversed),  this
  5327. is checked before \verb"objc_toggle" is called to do the highlighting and
  5328. selection  of  the  object,  which becomes the \verb"hot_obj".   (If  the
  5329. object was already \verb"SELECTED", the \verb"hot_obj" becomes NIL.)
  5330.  
  5331.      The  toughest  condition  is when the  mouse  is  within  the
  5332. dialog,  but  not over a mouse-sensitive object.   The regular GEM
  5333. event  structure  will not work,  because it can only wait on  two
  5334. rectangles,  and  there  may be many more selectable objects in  a
  5335. dialog  tree.   I have found a way around this limitation using  a
  5336. combination of the \verb"map_tree" utility
  5337. with the principle of visual hierarchy in object trees.
  5338.  
  5339.      In  summary,  the  algorithm  attempts to  find  the  largest
  5340. bounding rectangle around the current mouse position, within which
  5341. there are no mouse-sensitive objects.   It starts with a rectangle
  5342. equal  to the dialog root,  and successively "breaks" it with  the
  5343. rectangle of each mouse-sensitive object.  The next few paragraphs
  5344. examine this method in detail.
  5345.  
  5346.      Since  C  lacks  the  dynamic scoping  of  LISP,  from  which
  5347. \verb"map_tree" was derived, it is necessary to set up some globals to be
  5348. used during the rectangle break process.   \verb"Br_rect" is the \verb"GRECT" of
  5349. the current bounding rectangle.   \verb"Br_mx" and \verb"br_my" hold the current
  5350. mouse position.   \verb"Br_togl" is a switch which determines whether the
  5351. next  break will be attempted horizontally or  vertically.   After
  5352. initializing these variables, \verb"form_hot" uses \verb"map_tree" to invoke the
  5353. \verb"break_obj" routine for every object in the dialog.
  5354.  
  5355.      \verb"Break_obj"  first intersects the rectangle of the object  with
  5356. the  current  bounding  rectangle.   If they  are  disjoint,  then
  5357. neither  the object nor any of its offspring can  possible  affect
  5358. the  operation,  so FALSE is returned,  causing \verb"map_tree" to ignore
  5359. the subtree.
  5360.  
  5361.      The  object is next checked to see if it is  mouse-sensitive.
  5362. As before, it must be \verb"SELECTABLE" and not \verb"DISABLED", and it must not
  5363. be  hidden (this was checked automatically by  \verb"objc_find"  before).
  5364. If  these  conditions are met,  then the object intrudes into  the
  5365. current  bounding rectangle.   To maintain the desired  condition,
  5366. part of the rectangle must be removed or "broken away".
  5367.  
  5368.      In  many  cases,  the  break  operation can  be  done  either
  5369. horizontally or vertically.  Since we have no prior information as
  5370. to which way the mouse will move next,  \verb"break_obj" uses the \verb"br_togl"
  5371. flag to alternate which direction it will try first.   This should
  5372. yield the most nearly square rectangle.
  5373.  
  5374.      The  \verb"break_x" and \verb"break_y" routines are very similar.   In each
  5375. case,  the  segment occupied by the breaking object is compared to
  5376. the  point  occupied  by the mouse.   If the point is  within  the
  5377. segment,  there is no possible break in this dimension,  and FALSE
  5378. is  returned.   If  the point lies outside the segment,  then  the
  5379. rectangle  may be successfully broken by reducing this  dimension.
  5380. This is done, and TRUE is returned to report success.
  5381.  
  5382.      The \verb"break_y" routine also employs a look-ahead test to prevent
  5383. a possible infinite loop.   It is conceivable,  though not likely,
  5384. that someone might nest a non-\verb"SELECTABLE" object completely  within
  5385. another  \verb"SELECTABLE" object(s).   If the mouse point is within such
  5386. an  object,  the  algorithm  will not be able to  select  a  break
  5387. dimension.   In the current version, the mouse rectangle is simply
  5388. forced  to  a single pixel for this case.   (Note that is  is  NOT
  5389. sufficent to simply wait on the non-selectable object's rectangle,
  5390. since  other \verb"SELECTABLE" objects may overlap it and follow  it  in
  5391. tree order.)
  5392.  
  5393.      Since \verb"map_tree" examines all possible objects, \verb"br_rect" will be
  5394. the  correct bounding rectangle at completion.   Note that you can
  5395. readily  adapt this technique to other uses,  such as hot-spotting
  5396. while  dragging  objects.   It  is  much  less  demanding  of  CPU
  5397. resources than other methods, such as repetitive \verb"objc_finds".
  5398.  
  5399. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5400. \subsection{What a character!}
  5401.  
  5402.   The \verb"form_keybd" routine acts as a filter on
  5403. character  input.   When  it  recognizes a control  character,  it
  5404. processes it and zeroes the keyboard word.  Other chararacters are
  5405. passed on to \verb"objc_edit" to be inserted in \verb"edit_obj".  If there is no
  5406. editing object, the character goes to the bit bucket.
  5407.  
  5408.      The   \verb"form_keybd"   given   implements   the   standard    GEM
  5409. functionality with two minor additions.   First, a carriage return
  5410. in  a dialog with no \verb"DEFAULT" exit object is taken as a tab.   This
  5411. allows  <CR> to be used "naturally" in dialogs with several  lines
  5412. of text input.   Second,  tabs and backtabs "wrap around" from top
  5413. to  bottom  of  the dialog,  and are done by "walking  the  tree",
  5414. rather  than relying on the \verb"LASTOB" flag to signal the end  of  the
  5415. dialog.   This  allows the new form manager to handle dialog trees
  5416. which are not contiguous in memory.
  5417.  
  5418.      The  code sets up several global variables for use by  mapped
  5419. functions.   \verb"fn_obj" is the output from both \verb"find_tab" and
  5420. \verb"find_def". \verb"fn_dir" is an input to \verb"find_tab". 
  5421. \verb"Fn_last", \verb"fn_prev", and \verb"fn_last" are used while
  5422. searching for tab characters.
  5423.  
  5424.      A  carriage  return results in a search of the  entire  tree,
  5425. using  \verb"map_tree" and \verb"find_def",  for an object with its
  5426. \verb"DEFAULT" flag set.  Its \verb"SELECTED" flag is set and it is
  5427. inverted on the screen to indicate  the action taken.  
  5428. \verb"Form_keybd" returns a FALSE to  force termination  of  the main
  5429. \verb"form_do" loop.   If no \verb"DEFAULT" is  found, control passes
  5430. to the tab code.
  5431.  
  5432.      The  tabbing  procedure is somewhat complicated  because  the
  5433. same code is used for forward and backward tabbing.  The old value
  5434. of \verb"edit_obj" (the object being tabbed FROM) is placed into
  5435. \verb"fn_last". \verb"fn_dir"  is set to one for a forward tab, and
  5436. zero for a  backward tab.
  5437.  
  5438.      The general strategy is to scan the entire tree for  \verb"EDITABLE"
  5439. objects,  always  saving  the  last one found  in  \verb"fn_prev".   When
  5440. tabbing  forward  \verb"fn_last"  is checked against  \verb"fn_prev".  
  5441. A  match indicates  that  the  current object is  the  one  desired.   When
  5442. tabbing  backward the current object is checked  against  \verb"fn_last".
  5443. If  they  match,  \verb"fn_prev" is the desired object.   This  procedure
  5444. requires two passes when the tab "wraps around" the tree, that is,
  5445. when  the  desired object as at the opposite end of  the  traverse
  5446. from the old editing object.
  5447.  
  5448.      The  result  of  the  tab  operation  is  written  back  into
  5449. \verb"form_do's"  \verb"next_obj" parameter,  and becomes the new editing
  5450. object at the beginning of the next loop.
  5451.  
  5452. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5453. \subsection{Button down}
  5454.  
  5455.   The \verb"form_button" procedure is lengthy because it
  5456. must  recognize  and  handle  mouse clicks  on  several  types  of
  5457. objects:  \verb"EDITABLE",  \verb"SELECTABLE", and \verb"TOUCHEXIT".  The first section
  5458. of code rejects other objects, which cannot accept a click.
  5459.  
  5460.      The  next  piece of \verb"form_button" makes a special check  for  a
  5461. double click on a \verb"TOUCHEXIT" object.   This will cause the high bit
  5462. of the returned object number to be set.   (By the way,  this also
  5463. occurs  in  the standard \verb"form_do".)  This flag allows  user  dialog
  5464. code to perform special processing on the object.
  5465.  
  5466.      The largest piece of \verb"form_button" handles the various cases in
  5467. which the \verb"SELECTABLE" flag may be set.   Setting the \verb"RBUTTON" (radio
  5468. button) flag causes all of the object's siblings in the tree to be
  5469. deselected  at  the  time the object  is  clicked.   The  \verb"do_radio"
  5470. routine uses the \verb"get_parent" utility to find the ancestor, and then
  5471. performs the deselect/select operation.
  5472.  
  5473.      If the \verb"SELECTABLE" object is not \verb"TOUCHEXIT", then \verb"graf_watchbox"
  5474. is used to make sure that the mouse button comes back up while  it
  5475. is within the object.  Otherwise, the click is cancelled.  Care is
  5476. necessary  here,  since the hot-spot code may have already set the
  5477. \verb"SELECTED" flag for the object.   (We cannot be sure of this,  for a
  5478. race condition may have occurred!)
  5479.  
  5480.      If  the \verb"SELECTABLE" object is \verb"TOUCHEXIT",  then the application
  5481. has requested that \verb"form_do" exit without waiting for the button  to
  5482. go back up.   In both this and regular \verb"form_do",  \verb"TOUCHEXIT" objects
  5483. are  used when you want to provide immediate response  (animation)
  5484. within the context of a dialog.
  5485.  
  5486.      The  final parts of \verb"form_button" do cleanup.   If the  clicked
  5487. object  was  already hot-spotted,  \verb"hot_obj" must be reset  to  NIL,
  5488. otherwise  \verb"form_do"  will carefully unselect the object  which  has
  5489. just been selected!
  5490.  
  5491.      If  the  \verb"EXIT" or \verb"TOUCHEXIT" flags are  in  force,  \verb"form_button"
  5492. returns  FALSE to force the completion of \verb"form_do".   For  \verb"EDITABLE"
  5493. objects,  \verb"next_obj"  is left intact to replace \verb"edit_obj" during  the
  5494. next  loop.   Otherwise,  \verb"next_obj" has done its job and is zeroed,
  5495. and \verb"form_button" returns TRUE for continuation.
  5496.  
  5497.      This  concludes the tour of the alternate \verb"form_do".   The best
  5498. cure for any confusion in this explanation is to compile the  code
  5499. into  an  application  and  watch  how  it  runs  with   different
  5500. resources,  or attack it with a debugger.
  5501.  
  5502. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5503. \subsection{Operators are standing by}
  5504.  
  5505.   I encourage you to modify  this
  5506. code  to meet your particular needs and incorporate it  into  your
  5507. application.   I  would  like to request than anyone who comes  up
  5508. with  significant improvements (or bug fixes) send them to  me  so
  5509. they  can  be made generally available.   You can do this via  the
  5510. ANTIC ONLINE Feedback, or by sending E-mail to 76703,202.
  5511. \newpage
  5512.  
  5513.  
  5514. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5515. \newpage
  5516. \section{Coping With GEMDOS}
  5517.  
  5518. While it's fun playing with windows and object trees, one of the day-to-
  5519. day realities of working with the ST is its operating system, GEMDOS. A 
  5520. successful application should insulate the user from the foibles and 
  5521. occasional calamities of the machine's file system. The GEM environment 
  5522. provides some minimal tools for doing this, but a good deal of 
  5523. responsibility still rests with you, the programmer.
  5524.  
  5525. This chapter tries to address the GEM/DOS 
  5526. integration problem by providing you some stock code for common 
  5527. functions, along with a discussion of some of the worst "gotchas" 
  5528. lurking for the unwary. The source for this column is called {\tt GEMCL15.C}.
  5529.  
  5530.  
  5531. \subsection{Another bit of history}
  5532.  
  5533. There has been a good deal of confusion in the Atari press and among 
  5534. developers over what GEMDOS is, and how it relates to TOS and CP/M-68K. 
  5535. It's important to clear this up, so you can get a true picture of what 
  5536. GEMDOS is intended to do. The best way is to tell the story of GEMDOS' 
  5537. origins, which I can do, because I was there.
  5538.  
  5539. As most developers are aware, GEM was first implemented on the IBM PC. 
  5540. PC GEM performed two functions. The first was a windowed graphics 
  5541. extension to the PC environment. The second was a visual shell, the 
  5542. Desktop, which ran on top of the existing operating system, PC-DOS.
  5543.  
  5544. When work started on moving GEM to the ST, there were two big problems. 
  5545. First, no STs actually existed. Second, there was no operating system on 
  5546. the 68000 with which GEM and the Desktop could run. Unix was too large, 
  5547. and CP/M-68K lacked a number of capabilities, such as hierarchical 
  5548. files, which were needed to support GEM.
  5549.  
  5550. Work on porting the graphics parts of GEM to the 68000 had to start 
  5551. immediately to meet schedules. Therefore, CP/M-68K running on Apple 
  5552. Lisa's was used to get this part of the project off the ground. 
  5553. Naturally, the Alcyon C compiler and other tools which were native to 
  5554. this environment were used.
  5555.  
  5556. In parallel, an effort was begun to write a new operating system for the 
  5557. 68000, which would ultimately become the ST's file system. It was 
  5558. designed to be a close clone of PC-DOS, since it would perform the same 
  5559. functions for GEM in the new environment. At this point, the term TOS 
  5560. was introduced. TOS really meant "the operating system, whatever it may 
  5561. be, that will run on the ST", since not even the specifications, let 
  5562. alone the code, were complete at that time.
  5563.  
  5564. The first engineer to work on "TOS" at Digital Research was Jason 
  5565. Loveman. This name leaked to the press, and in some distorted fashion 
  5566. generated a rumor about "Jason DOS", which was still just the same 
  5567. unfinished project. As "TOS" became more solid, the developer's tools 
  5568. were ported to the new environment one by one, and the GEM programming 
  5569. moved with them. CP/M-68K was completely abandoned, though the old 
  5570. manuals for C and the tools lived on and are still found in the Atari 
  5571. developer's kit.
  5572.  
  5573. All of this work had been done on Lisas or Compupro systems fitted with 
  5574. 68000 boards. At this point, workable ST prototypes became available. An 
  5575. implementation of "TOS" for the target machine was begun, even before 
  5576. the basic operating system was fully completed.
  5577.  
  5578. The other intent for the new operating system was to be a base for GEM 
  5579. on other 68000 systems as well as the ST. Because of this, Digital 
  5580. Research named it GEMDOS when it was finally complete, thus providing 
  5581. the final bit of nomenclature. "TOS" as now found in the ST is in fact a 
  5582. particular implementation of generic GEMDOS, including the ST specific 
  5583. BIOS.
  5584.  
  5585. So, GEMDOS is a PC-DOS clone, but, not quite. There are enough 
  5586. differences to cause problems if they are ignored. (Remember, it looks 
  5587. like a duck, and quacks like a duck, but it's not a duck.)
  5588.  
  5589.  
  5590. \subsection{Going for it}
  5591.  
  5592. As a first example, consider the routines {\tt open\_file()} and {\tt create\_file()} 
  5593. at the beginning of the listing. They make use of the GEMDOS calls 
  5594. \verb"Fopen()" and \verb"Fcreate()". You will notice that these names are not the ones 
  5595. specified in the Digital Research GEMDOS manual. Developers who have 
  5596. used PC GEM will also observe that they are radically different from the 
  5597. function names in the PC-DOS bindings.
  5598.  
  5599. In fact, all of the GEMDOS function calls on the ST are defined as 
  5600. macros in the file osbind.h, distributed with the developer's kit. At 
  5601. compile time they are turned into calls to the assembly language routine 
  5602. {\tt gemdos()}, part of the osbind.o binary. So, if you find the naming 
  5603. conventions to be particularly offensive for some reason, just edit the 
  5604. appropriate macros in osbind.h.
  5605.  
  5606. In DRI's PC-DOS bindings, any error codes were returned in the global 
  5607. variable \verb"DOS_ERR". In the GEMDOS bindings, the operation result or an 
  5608. error code is returned as the value of the calling function. In the case 
  5609. of \verb"Fopen()" and \verb"Fcreate()", the result is a valid file handle if it is 
  5610. positive. A negative result is always an error code, indicating that the 
  5611. operation failed.
  5612.  
  5613. An application which encounters a GEMDOS error should display an alert, 
  5614. and query for retry or abort. The type of loop structure exemplified by 
  5615. {\tt open\_file()} and {\tt create\_file()} should be usable with most GEMDOS 
  5616. functions which might fail. The AES provides a function, \verb"form_error", 
  5617. which implements a set of "canned" error alerts appropriate to the 
  5618. various possible errors.
  5619.  
  5620. However, this is where the fun starts. For unknown reasons, the 
  5621. \verb"form_error" on the ST expects to see PC-DOS, not GEMDOS, error codes as 
  5622. it's input! Therefore you need a routine to translate one into the 
  5623. other. The routine {\tt dos\_error()} in the listigs provides this function. 
  5624. The GEMDOS errors are in the same sequence as those for PC-DOS, but 
  5625. their numerical order is reversed and shifted. Notice also that 
  5626. {\tt dos\_error()} does NOT perform the translation if the error code is less 
  5627. than -50. These codes have no PC-DOS equivalent; computing a bogus 
  5628. translation will cause \verb"form_error" to crash. Instead, they are passed 
  5629. through verbatim, resulting in a "generic" alert which gives only the 
  5630. error number.
  5631.  
  5632. The other major task in integrating a GEM application with the file 
  5633. system is selecting file names for input and output. Again, the AES 
  5634. provides some assistance with the \verb"fsel_input" call, which invokes the 
  5635. standard file selector dialog.
  5636.  
  5637. There are several drawbacks to the standard file selector. One is that 
  5638. the "ITEM SELECTOR" title is constant and cannot be changed by the 
  5639. application. This could cause confusion for the user, since it may not 
  5640. be clear which of several functions, closely spaced in the FILE menu, 
  5641. was actually invoked. While it might be possible to find and "rewire" 
  5642. the AES resource that defines the file selector, it is unlikely that 
  5643. such an approach would be portable to a later version of ST GEM.
  5644.  
  5645. A viable approach to eliminating confusion is to display a small 
  5646. "marquee" box, with a message defining the operation, on the screen just 
  5647. above the file selector. To do this, you must initialize the location of 
  5648. the box so that it is outside of the file selector's bounds, and then 
  5649. draw it just before invoking the file selector. This way they will 
  5650. appear together. Before returning to its main event loop, the 
  5651. application should post a redraw message for the "marquee" area. The AES 
  5652. will merge this redraw with the one generated by \verb"fsel_input", and the 
  5653. result will be received by the application's \verb"evnt_multi".
  5654.  
  5655. Later versions (since TOS 1.4) of the ST GEM provide the \verb"fsel_exinput"
  5656. call that allows the programmer to specify a title line. But since this
  5657. call is not available on older machines we have to check which version
  5658. of TOS is installed, and may have to call the old routine after all.
  5659.  
  5660. Another problem with the file selector is that it resets your 
  5661. application's virtual workstation clip rectangle without warning. There 
  5662. are other AES functions, such as \verb"objc_draw", which also do this, but the 
  5663. file selector can be troublesome because it may be the only AES call 
  5664. used by some VDI-based ST applications.
  5665.  
  5666. The veteran developer will also notice that the file selector takes and 
  5667. returns the path and filename as two separate strings, while the GEMDOS 
  5668. file functions require a fully pathed file name. Also, the file selector 
  5669. doesn't remember its "home" directory; you are responsible for 
  5670. determining the default directory, and keeping track of any changes. The 
  5671. remainder of the listing and chapter is devoted to set of utilities 
  5672. which should alleviate some of the "grunt work" of these chores.
  5673.  
  5674. The top level routine in this collection is {\tt get\_file()}. It is called 
  5675. with two string arguments. The first must point to a four byte string 
  5676. area containing the desired file name extension (three characters plus a 
  5677. null). The second is the default file name.
  5678.  
  5679. If the default file name is non-null, then {\tt get\_file()} invokes 
  5680. {\tt parse\_fname()} to break it into path and name. {\tt Parse\_fname()} also adds 
  5681. the necessary "wild card" file specification to the path, using the 
  5682. extent name given as input.
  5683.  
  5684. If no default file was supplied, or the default did not contain a path, 
  5685. the routine {\tt get\_path()} is invoked to find the current default directory 
  5686. and construct a legal path string for it.
  5687.  
  5688. The results of these manipulations are supplied to \verb"fsel_input". Notice 
  5689. that the result of the file selector is returned via its third argument, 
  5690. rather than as a function value. If the result is TRUE, {\tt get\_file()} 
  5691. merges the temporary path and file string, storing the result via the 
  5692. second input parameter. This result string is suitable for use with 
  5693. Fopen, and may be resubmitted to {\tt get\_file()} when the next operation is 
  5694. invoked by the user.
  5695.  
  5696. {\tt Parse\_fname()} is straight-forward C. It looks backward along the file to 
  5697. find the first character which is part of the path. The tail of the 
  5698. filename is copied off, and its former location is overlaid with the 
  5699. wild card specification.
  5700.  
  5701. {\tt Get\_path()} is a bit more interesting. It makes use of two GEMDOS 
  5702. functions, \verb"Dgetdrv()" and \verb"Dgetpath()" to obtain the default disk drive and 
  5703. directory, respectively. Note that \verb"Dgetpath()" will return a null string 
  5704. if the current default is the root, but it puts a back-slash at the 
  5705. beginning of the path otherwise. This forces a check for insertion in 
  5706. the root case, since the file selector wants to see something like 
  5707. \verb"A:\*.RSC", rather than \verb"A:*.RSC". After making this fix, {\tt get\_path()}
  5708. concatenates the wild card specification derived from the input extent.
  5709.  
  5710. The last routine in the listing is {\tt new\_ext()}. This utility is useful if 
  5711. your application uses more than one associated file at a time. For 
  5712. instance, the Resource Construction Set uses both an RSC and a DEF file, 
  5713. with the same base name. {\tt New\_ext()} takes a fully formed file name, and 
  5714. replaces its old extent with the new one which you supply. This lets you 
  5715. quickly generate both file names after one call to the file selector. 
  5716. Notice that {\tt new\_ext()} looks BACKWARD along the name to find the 
  5717. delimiting period, since this character can also be part of a 
  5718. subdirectory name in the path.
  5719.  
  5720. So we reach the end of the code and this chapter. Hopefully both will 
  5721. keep you profitably occupied for a while. The next chapter will return to 
  5722. graphics topics, with a look at writing customized rubber box and drag 
  5723. box routines.
  5724.  
  5725. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5726. \newpage
  5727. \section{Interface Potpourri}
  5728.  
  5729. This chapter of ST PRO GEM presents code 
  5730. implementing several user interface techniques: progress indicators, 
  5731. rubber boxes, and draggable boxes with mouse sensitive targets. The code 
  5732. also includes some utility routines for handling resources, event calls, 
  5733. and VDI line drawing.
  5734.  
  5735. There are several files for this column. Note the plural - in addition 
  5736. to the usual C sources stored in {\tt GEMCL16.C}, the files {\tt GEMCL16.RSC}, 
  5737. {\tt GEMCL16.DFN}, {\tt GEMCL16.H}, and {\tt GEMCL16.RSH} are a template resource for 
  5738. building progress boxes. {\tt GEMCL16.RSC} is the resource binary, and 
  5739. {\tt GEMCL16.H} is its symbol binding file, to be used with {\tt GEMCL16.C}. The RSH 
  5740. file is a C image of the resource - you would need {\tt STCREATE} to 
  5741. regenerate it.
  5742.  
  5743. {\tt GEMCL16.DFN} is the binary symbol file for the resource. It is in the 
  5744. format used by the NEW ST Resource Construction Set. This fixes a number 
  5745. of bugs, and has a much faster user interface.
  5746.  
  5747.  
  5748. \subsection{Making Progess}
  5749.  
  5750. The need for feedback in interface designs has been discussed in 
  5751. previous chapters. One instance which is often necessary is the so-called 
  5752. progress indicator. A progress indicator is used when your application 
  5753. is doing a long operation. It shows that the function is continuing 
  5754. satisfactorily, and is not hung in a loop. When possible, it also gives 
  5755. an indication of the fraction of the operation which has been completed. 
  5756. The thermometer bars on the Desktop format and copy operations are 
  5757. examples.
  5758.  
  5759. The sample code shows two types of progress indicator. Both are built 
  5760. within the structure of a dialog resource. The first type uses a 
  5761. variable line of text to describe each phase of an operation as it 
  5762. occurs. The rewriting of the text provides action on the screen; the 
  5763. fact that it is different each time gives reassurance that the program 
  5764. is not hung. The second type of indicator is the thermometer bar. This 
  5765. is more useful when the operation is uniform, allowing you to estimate 
  5766. the fraction completed. Let's look at the code.
  5767.  
  5768. The routines {\tt beg\_prog()} and {\tt end\_prog()} are common to the two types. The 
  5769. code is very similar to the standard dialog handling procedure, but is 
  5770. broken into two parts. {\tt Beg\_prog()} assumes that the progress indicator 
  5771. box is defined by a dialog tree named {\tt PROGRESS}. Such a tree is provided 
  5772. in {\tt GEMCL16.RSC}. Beg\_prog() makes the usual calls to center and draw the 
  5773. box. The rectangle computed in the centering operation is stored via a 
  5774. \verb"GRECT" pointer passed in the parameter. This rectangle compensates for 
  5775. the outline around the box, and must be supplied to {\tt end\_prog()} when the 
  5776. operation is complete.
  5777.  
  5778. The first version of {\tt set\_prog()} in the code implements the changing 
  5779. text progress indicator. It looks in a tree labelled \verb"STRINGS" for the 
  5780. object number which is passed as a parameter. It is assumed that this 
  5781. object is a \verb"G_STRING". The address of the new text is loaded from the 
  5782. object's \verb"ob_spec" field. (For those with the new RCS, it would be easy to 
  5783. alter this routine to use free strings. Simply replace the first two 
  5784. lines with: \verb"rsrc_gaddr(R_STRING, strno, &saddr);" and supply parameters 
  5785. which are the names of strings in a \verb"FRSTR" box.)
  5786.  
  5787. Once the new text is found, the {\tt set\_text()} utility is called to update 
  5788. the \verb"TEDINFO" attached to object \verb"PLINE" in the \verb"PROGRESS" tree. {\tt Set\_text()} 
  5789. will insert the new text address in \verb"te_ptext", and the new text length in 
  5790. \verb"te_txtlen". {\tt Disp\_obj()} is then used to redraw only the rectangle 
  5791. belonging to \verb"PLINE".
  5792.  
  5793. \verb"PLINE" must be defined as a \verb"G_BOXTEXT" object with a solid white 
  5794. background, and with the \verb"CENTERED" attribute set. It must extend entirely 
  5795. across the progress box. This guarantees that the previous text will be 
  5796. covered over, and the new text will be centered in the box.
  5797.  
  5798. The second version of {\tt set\_prog()} implements the thermometer bar progress 
  5799. indicator. The \verb"PROGRESS" tree also includes an object \verb"PROBOX" which 
  5800. defines the outline of the thermometer. It is a \verb"G_BOX" object with a 
  5801. solid white background, and a one-outside border. The object \verb"PROBAR" is 
  5802. nested inside it, with the left edges matching. \verb"PROBAR" is also a \verb"G_BOX", 
  5803. with a solid red background and a one-outside border as well. {\tt Set\_prog()} 
  5804. creates the thermometer effect by growing and redrawing \verb"PROBAR".
  5805.  
  5806. {\tt Set\_prog()} requires two parameters. Maxc is an estimate of the total 
  5807. duration of the operation, in arbitrary units. Value is the (new) amount 
  5808. completed, in the same units. {\tt Set\_prog} performs two operations. First, 
  5809. it computes the fraction value/maxc, and sets \verb"PROBAR" to that fraction of 
  5810. the width of \verb"PROBOX". Second, it computes the rectangle which is the 
  5811. difference between the old and new widths of \verb"PROBAR", and redraws only 
  5812. that part of the progress box. This prevents an annoying flash on the 
  5813. screen when the indicator is updated.
  5814.  
  5815. These two types of progress indicators have been presented in separate 
  5816. routines for convenience in explanation. You can easily combine them in 
  5817. a single procedure to create an indicator with both effects.
  5818.  
  5819. The final progress indicator routine is called {\tt esc\_prog()}. During many 
  5820. lengthy operations is desirable to provide an abort option to the user. 
  5821. {\tt Esc\_prog()} lets you do this by polling the keyboard for an escape (ESC)
  5822. character. A zero timer value is used to guarantee an immediate return 
  5823. if no character is found. Characters other than escape are ignored.
  5824.  
  5825. {\tt Esc\_prog()} returns \verb"TRUE" if an abort is requested, and \verb"FALSE" if the 
  5826. operation is to continue. In your application, you can either pair calls 
  5827. to {\tt set\_prog()} and {\tt esc\_prog()}, or recode {\tt set\_prog()} to automatically make 
  5828. the abort check. In any case, you should add an information line to the 
  5829. progress box, telling the user how the operation may be halted.
  5830.  
  5831. Of course, this type of progress indicator is not the only option 
  5832. available on the ST. Other ideas such as changing window titles, or 
  5833. displaying a succession of differing icons are equally valid. Sometimes 
  5834. the nature of your application may suggest an alternate metaphor. For 
  5835. instance, the progress of recalculating a spreadsheet might be indicated 
  5836. by darkening successive columns in a miniature image of the sheet. 
  5837. Occasionally, the computing operation is visual itself, and will not 
  5838. require an explicit indicator. An example is redisplaying objects in a 
  5839. 2D or 3D drawing program.
  5840.  
  5841.  
  5842. \subsection{Boxed in}
  5843.  
  5844. The second part of the listing implements two types of user interaction 
  5845. using the mouse. The first creates a "rubber box" on the screen, that 
  5846. is, a box whose size is controlled by moving the mouse. This is similar 
  5847. to the AES \verb"graf_rubberbox" call, but allows the box to move in any 
  5848. direction from its origin, while the GEM function only allows movement 
  5849. to the lower right. The AES \verb"graf_rubberbox" call does allow movement
  5850. in any direction however if the maximum values for the box are NEGATIVE.
  5851. The resulting rectangle may have to be corrected if the upper left corner
  5852. has changed.
  5853.  
  5854. The second technique allows the user to drag the outline of a box around 
  5855. the screen using the mouse. Again, this is similar to the AES 
  5856. \verb"graf_dragbox" call, but this version is augmented with code which 
  5857. "hotspots" selectable objects when the mouse and object pass over them. 
  5858. These routines are another illustration of the usage of the \verb"evnt_multi" 
  5859. function, and its combination with VDI drawing to create new interaction 
  5860. techniques.
  5861.  
  5862. The "rubber box" subroutine is called {\tt fourway\_box()}. Its parameters are 
  5863. the current VDI handle (NOT a window handle!), and two \verb"GRECT" pointers. 
  5864. The first \verb"GRECT" must have its \verb"g_x" and \verb"g_y" initialized with the fixed 
  5865. point of the rubber box. The second GRECT contains an outer bound box 
  5866. for the stretching action.
  5867.  
  5868. {\tt Fourway\_box()} begins by setting the VDI drawing mode and color. The 
  5869. exclusive or, black combination guarantees that redrawing a figure twice 
  5870. in the same location will exactly erase it. Next, the routine asserts 
  5871. the mouse control flag. This stops the window manager from tracking the 
  5872. mouse, with the effect that menus will not drop down during the 
  5873. operation.
  5874.  
  5875. The fixed coordinates are saved in the variables {\tt ox} and {\tt oy}, and an 
  5876. initial mouse reading is obtained with \verb"graf_mkstate". At this point, the 
  5877. event loop is entered.
  5878.  
  5879. At each iteration, the loop finds the upper left most of the fixed 
  5880. vertex and the current mouse position, and updates the tracking \verb"GRECT" 
  5881. accordingly. A call to the utility {\tt rc\_intersect()} is used to restrict 
  5882. the size of the rubber box to the given limiting rectangle. Note that if 
  5883. you need a lower limit to the size of the rubber box, it can be achieved 
  5884. by adding another \verb"GRECT" pointer "lower" to the parameter list, and using 
  5885. the call {\tt rc\_union(lower, rubber);} This works because the union operation 
  5886. selects the larger of two rectangles if they are nested.
  5887.  
  5888. {\tt Rub\_wait()} will be described in detail below. Its returns are the new 
  5889. mouse position, and an indication of the current mouse button state. If 
  5890. the button remains down, the loop continues. When the button is 
  5891. released, the rubber box terminates, since it is a "spring-loaded" modal 
  5892. operation. Before ending, {\tt fourway\_box()} returns mouse control to the 
  5893. window manager. The return from the routine is found in the rubber 
  5894. \verb"GRECT", and is the final extent of the box.
  5895.  
  5896. {\tt Rub\_wait()} is a utility used by both box techniques. Its purpose is to 
  5897. do one step of the box animation, and wait for a mouse movement, or the 
  5898. release of the button. {\tt Rub\_wait()} preserves the state of the screen.
  5899.  
  5900. The first action is to draw an exclusive or'ed dotted line box at the 
  5901. given rectangle. Next, {\tt rub\_wait()} calls \verb"evnt_multi" to wait for the mouse 
  5902. button to come up, or the mouse to move out of a one pixel rectangle. 
  5903. When the event is detected, the same code is used to remove the box. A 
  5904. value of \verb"TRUE" is returned if the mouse button is still down; the curious 
  5905. logical construction is necessary since BOTH events could occur at once.
  5906.  
  5907. A short examination of the {\tt vdi\_xbox()} code is also useful. After 
  5908. converting the rectangle to polyline format, the {\tt vdi\_xline()} routine is 
  5909. called. {\tt Vdi\_xline} draws a dotted line, but does not use the VDI line 
  5910. style attribute. This is avoided because the VDI has problems with 
  5911. corner points when drawing styled lines in \verb"XOR" mode. Instead, a 
  5912. selection is made from a set of user defined line styles, based on the 
  5913. direction of the stroke, and the odd/evenness of the starting horizontal 
  5914. pixel. This assures that the figure will be exactly erasable.
  5915.  
  5916.  
  5917. \subsection{Hot Stuff?}
  5918.  
  5919. The drag box routine is more subtle, because care is needed to correctly 
  5920. synchronize the movement of the mouse cursor and the box, and the 
  5921. highlighting of target objects. The parameters {\tt vdi\_handle} and {\tt limit} are 
  5922. identical to those in {\tt fourway\_box()}. The \verb"GRECT" pointed to by box 
  5923. contains the width and height of the movable box when {\tt hot\_dragbox()} is 
  5924. entered. On exit it also contains the last x,y coordinates of the box. 
  5925. The variable tree is a pointer to the root of a resource tree defining 
  5926. the hot spots for the drag operation. Only objects tagged \verb"SELECTABLE" are 
  5927. hotspotted. {\tt Hot\_dragbox()} returns the number of such an object if the 
  5928. box is "dropped" on it, otherwise a NIL is returned.
  5929.  
  5930. Initialization proceeds as above, until the \verb"graf_mkstate" call. Here is 
  5931. the first potential synchronization problem. If the user moves the mouse 
  5932. very quickly after initiating the drag, it may already be outside the 
  5933. box by the time \verb"graf_mkstate" samples the position. The \verb"min/max" 
  5934. operations given lock the box onto the cursor, no matter where it has 
  5935. strayed. The mouse/box offsets, {\tt ox} and {\tt oy}, will remain constant for the 
  5936. rest of the operation.
  5937.  
  5938. {\tt Hover\_obj} will contain the number of the object which is currently 
  5939. highlighted. It is initialized to \verb"NIL", indicating no object is currently 
  5940. marked. {\tt Hot\_dragbox()} now enters a loop with termination conditions 
  5941. identical to the rubber box.
  5942.  
  5943. The current desired position of the box is computed by subtracting the 
  5944. box/mouse offset from the current mouse position. The {\tt rc\_constrain()} 
  5945. call ensures that the box will not leave the bounding rectangle. Note 
  5946. that {\tt rc\_intersect} would not work here - it would alter the size of the 
  5947. draggable box, rather than "nudging" it back into the bounds.
  5948.  
  5949. Upon return from {\tt rub\_wait()}, a number of conditions must be checked to 
  5950. determine the correct object to highlight, if any. First, we must make 
  5951. sure that the mouse is actually within the legal bounds. If not, there 
  5952. may be an ambiguous selection, with the mouse over one object and the 
  5953. box over another. We choose to do nothing in this case, and set 
  5954. {\tt hover\_obj} to \verb"NIL". If the mouse is in bounds, \verb"objc_find" looks for a 
  5955. target object. If one exists, it must be \verb"SELECTABLE", or it is forced to 
  5956. \verb"NIL".
  5957.  
  5958. Next the new object, stored in {\tt ret\_obj}, is compared to the old 
  5959. highlighted object, in {\tt hover\_obj}. If they are different, a switch must 
  5960. be made. Since either could be \verb"NIL", a check is necessary before calling 
  5961. {\tt obj\_toggle} to invert/reinvert the screen image of the object. When the 
  5962. loop is complete, the final {\tt hover\_obj} is returned to normal state before 
  5963. its number is returned.
  5964.  
  5965. You may notice that this method of highlighting objects is different 
  5966. from the incremental tree descent and rectangles method presented earlier.
  5967. While not as efficient, the \verb"objc_find" technique is simpler to 
  5968. code and may be adequate for many uses. If your program will make heavy 
  5969. use of the drag box routine, or will have large trees of target objects, 
  5970. you may wish to integrate the incremental hotspotting algorithm with 
  5971. {\tt hot\_dragbox()}. This would be simple to do; just use \verb"evnt_multi"'s second 
  5972. mouse rectangle for the states associated with the hot-spotter. The 
  5973. single pixel rectangles would have to remain, in order to maintain the 
  5974. animation effects.
  5975.  
  5976. \subsection{R2D2, where are you?}
  5977.  
  5978. Finally, you may also notice that the so-called portability macros have 
  5979. disappeared from the listing. Indeed, they are gone for good. Since the 
  5980. beginning of this column, the growth of the ST GEM developer community 
  5981. has outstripped that on the PC. It no longer seems appropriate to 
  5982. inconvenience ST developers and violate standard C syntax for the sake 
  5983. of Intel's design flaws. Those who still need compatibility with the PC 
  5984. may achieve it by compiling under Intel large model, or by writing "sed" 
  5985. scripts to translate \verb"(tree+obj)->ob_spec" and the like to their macro 
  5986. equivalents.
  5987.  
  5988. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5989. \newpage
  5990. \section{PC/ST Resource Converter}
  5991.  
  5992.  
  5993. This chapter of ST PRO GEM is the first to feature a 
  5994. complete GEM application. The program converts resource files between 
  5995. the ST (68000) and IBM PC (Intel) formats used by the respective 
  5996. versions of GEM and the Resource Construction Set.
  5997.  
  5998. The Resource Converter will, for the most part, be of direct use only if 
  5999. you are doing cross-development of GEM software on these two systems. In 
  6000. this case, you will want to read this entire chapter, starting with the 
  6001. "What It Does" heading. You may also be interested in an article on 
  6002. PC/ST conversion written by Mark Skapinker of Batteries Included, which 
  6003. appears in the Fall 1986 issue of START magazine.
  6004.  
  6005. If you are not doing cross machine development, you can still get 
  6006. something out of this column. Reading the program code and following the 
  6007. discussion, you will find practical examples of using GEM dialogs and 
  6008. following the internal structure of a resource file. Finally, there is a 
  6009. good deal of standard code for GEM initialization, AES utility 
  6010. functions, and GEMDOS file handling which you can extract for your own 
  6011. uses. If you fall in this category, skip the first parts of the column, 
  6012. and resume reading at the "How it Works" heading.
  6013.  
  6014. The files and their contents for this chapter are:
  6015.  
  6016. \begin{description}
  6017.  
  6018. \item[RSCVMAIN.C  ] This is the C source for main routine
  6019. \item[RSCVFILE.C  ] This is the C source of GEMDOS utilities    
  6020. \item[RSCVLIB.C   ] C source of AES utility functions
  6021. \item[RSCONV.PRG  ] Linked binary of converter
  6022. \item[RSCONV.RSC  ] Binary resource image (ST format)
  6023. \item[RSCONV.DFN  ] Symbol file for resource (ST format for RCS 2.0)
  6024. \item[RSCONV.H    ] Object/tree name file for resource
  6025. \item[RSCVLINK.SH ] C-shell script for linking RSCONV
  6026.  
  6027. \end{description}
  6028.  
  6029. The final two files will be of use only if you are using Dave 
  6030. Beckemeyer's Micro C-Shell environment. If not, you can simply translate 
  6031. them to \verb".BAT" and/or \verb".INP" form for use with the Atari batch program and 
  6032. linker.
  6033.  
  6034.  
  6035. \subsection{What it does}
  6036.  
  6037. A converter program is necessary because of the differing order of 
  6038. storage on the 68000 and Intel chips: the order of significance of bytes 
  6039. within words is reversed, as well as the order of words within long (32-
  6040. bit) quantities. Attempting to load an unconverted resource on a GEM 
  6041. system with the other architecture will result in a crash, because all 
  6042. of the pointer and integer fields will be incorrect.
  6043.  
  6044. In addition, the format of symbol definition (DEF) files differs between 
  6045. the PC and ST implementations of the RCS in its first version. In the 
  6046. latest version from DRI, the formats do correspond, and the files now 
  6047. carry an extent name of DFN. However, the byte swapping problem must be 
  6048. corrected in either format for the symbols to be correctly loaded.
  6049.  
  6050. As final touch, the converter also checks to be sure that a resource 
  6051. being loaded from the PC has its bit images synchronized to an even byte 
  6052. boundary. If this is not corrected, the ST will suffer a bus error when 
  6053. attempted to address the images with a word type operation, which will 
  6054. certainly happen in either the RCS or the application itself on the 
  6055. target system.
  6056.  
  6057.  
  6058. \subsection{Operation}
  6059.  
  6060. When the Resource Converter loads, it presents an initial dialog box. 
  6061. (The converter does not use the menu bar.) The dialog has action buttons 
  6062. at the bottom labelled \verb"Help", \verb"Convert" and \verb"Quit". Clicking the Help 
  6063. button will obtain a screen which summarizes these operating 
  6064. instructions. The \verb"Quit" button terminates the program. Clicking \verb"Convert"
  6065. initiates the program's action, according to the options you have set in 
  6066. the rest of the dialog.
  6067.  
  6068. The top two buttons in the dialog establish the direction of the 
  6069. conversion. If you have built a resource on the PC and want to move it 
  6070. to the ST, click \verb"Intel->68000". If you are moving the file from the ST to 
  6071. the PC, click \verb"68000->Intel".
  6072.  
  6073. The next two lines in the dialog establish the file extent names which 
  6074. will be used for the conversion. The input extent names are always on 
  6075. the left, no matter which conversion mode you selected above. By 
  6076. default, they are \verb"RSC" and \verb"DEF". The output extents, on the right, are RS2 
  6077. and \verb"DF2" by default. The \verb"RSC/RS2" file extents are used for the resource, 
  6078. and \verb"DEF/DF2" extents are for the symbol file. Be careful that the input 
  6079. files you use are actually of the type (Intel or 68000) which you 
  6080. specified. If you get it backwards, the ST will most likely crash, 
  6081. though the input files will not be harmed.
  6082.  
  6083. The three buttons below the file extents determine the format of the 
  6084. input and output symbol files. If you click on \verb"DEF", the Resource 
  6085. Converter will assume that the input and output symbol files are in the 
  6086. old (that is, version 1.1) format used by the RCS. If you click on \verb"DFN", 
  6087. the program expects the new (version 2.0) symbol format. If the input 
  6088. symbol file extent is still set to \verb"DEF", clicking this button will also 
  6089. change it appropriately. (Note that the \verb"DEF" and \verb"DFN" formats are in fact 
  6090. IDENTICAL on the PC ONLY. To "change formats" ON THE PC, you need only 
  6091. change the file's extent name, for example, rename \verb"FOOBAZ.DEF" to 
  6092. \verb"FOOBAZ.DFN". On the ST, there is a real difference,and you must use the 
  6093. DRI \verb"DEF2DFN.PRG" utility to go from old to new.)
  6094.  
  6095. The last button option is (OFF). Clicking this button disables the 
  6096. symbol file conversion. You may use this option to keep better control 
  6097. over versions of your resource. By establishing the main version on 
  6098. either the PC or ST, and converting only the resource file, not the 
  6099. symbols, you can ensure that no one will use the RCS on the destination 
  6100. machine to create a version which is different from the source.
  6101.  
  6102. When the \verb"Convert" button is clicked to begin execution, the standard Item 
  6103. Selector is displayed. Use it to find and pick the input resource file 
  6104. which you want to convert. The Converter will use its main filename, 
  6105. substituting the various extents, to find the input definition file, and 
  6106. produce the output file names. If the definition file cannot be found in 
  6107. the same directory under the generated name, you will be presented with 
  6108. an alert, asking you to abort the conversion, continue without the 
  6109. symbol file, or specify a new name and/or directory for the file. If the 
  6110. output names coincide with existing files, they will be overwritten.
  6111.  
  6112. While the conversion operation is occurring, a progress indicator box 
  6113. will be displayed on the screen, with text messages indicating the 
  6114. current phase of the operation. When the conversion is complete, you are 
  6115. returned to the initial dialog, where you may quit or perform another 
  6116. conversion.
  6117.  
  6118. One last note on conversion, with a caution: it is possible to move 
  6119. files between Intel and 68000 even if you have two different versions of 
  6120. the Resource Construction Set, for instance, Version 2.0 on the PC and 
  6121. Version 1.1 on the ST. In this situation, you can take advantage of the 
  6122. identity between symbol file formats on the PC. Make a copy of the PC 
  6123. symbol file into another file with the \verb"DEF" extent, and run the 
  6124. converter. The output should load on the ST version correctly. However, 
  6125. if you move symbols between different RCS versions, you MUST NOT use the 
  6126. "free strings" and "free images" features of version 2 and then move the 
  6127. symbols to version 1. Doing so may result in spurious assignment of the 
  6128. "free" symbols to trees and objects, and you will (of course) not be 
  6129. able to edit the free images and/or strings in the resource.
  6130.  
  6131.  
  6132. \subsection{How it works}
  6133.  
  6134. For the ST-only developers now rejoining the discussion, I will now take 
  6135. a look at the standard GEM initialization code and the special dialog 
  6136. handling techniques which I have used in the Converter. Then we'll look 
  6137. at the guts of the code, which threads through the resource to do the 
  6138. actual conversion. For those interested in the supporting code 
  6139. libraries, the GEMDOS interface utilities in {\tt RSCVFILE.C} were described 
  6140. earlier. The progress indicator functions of {\tt RCSLIB.C} were 
  6141. detailed in the previous chapter, and {\tt map\_tree()} and standard dialog handling 
  6142. techniques were discussed in columns three through five.
  6143.  
  6144. There are a number of useful facts in {\tt rscv\_init()}, the initialization 
  6145. code. First, notice that the result of \verb"appl_init" is NOT assigned 
  6146. directly to \verb"gl_apid". Due to a bug in the \verb"appl_init" binding the 
  6147. application ID is not returned as the function value. Instead it is 
  6148. returned to the global variable \verb"gl_apid". This bug wouldn't cause direct 
  6149. problems in the resource converter, but it will in any program which 
  6150. uses the ID when sending messages to its own pipe.
  6151.  
  6152. Next, an alert string to be displayed if the resource is not found has 
  6153. been explicitly included, to avoid a "Catch-22" situation. You can 
  6154. easily create such a string by building the alert in the RCS, using the 
  6155. C output option, and extracting the string from the resulting file.
  6156.  
  6157. {\tt Rscv\_init()} then sets up its VDI handle, by getting the physical 
  6158. workstation handle from \verb"graf_handle", and passing it to \verb"v_opnvwk" (open 
  6159. virtual workstation), which returns the virtual workstation handle for 
  6160. use in VDI calls. \verb"V_opnvwk" also returns the dimensions of the screen, 
  6161. which are copied to \verb"GRECT scrn_area", and the number of color planes, 
  6162. which is used to set up an \verb"MFDB" for the screen: \verb"scrn_mfdb".
  6163.  
  6164. The \verb"wind_get" call for the working area of the DESK window (number zero) 
  6165. results in the usable \verb"GRECT" of the screen. This is different from 
  6166. \verb"scrn_area", because the menu bar's rectangle is reserved for the system.
  6167.  
  6168. You may want to take particular notice of the \verb"vst_height" call, which 
  6169. reloads the character dimension variables. The values returned earlier 
  6170. by \verb"graf_handle" are ALWAYS for the monochrome (high resolution) system 
  6171. font, and they are not appropriate for the low and medium resolution 
  6172. modes of the ST. Performing the \verb"vst_height" call AFTER opening the 
  6173. virtual workstation will get the correct dimensions.
  6174.  
  6175. Some of the environment variables which are set up by {\tt rscv\_init()}, are 
  6176. not actually used in the resource converter. I have included them 
  6177. because they are part of my "generic" initialization procedures.
  6178.  
  6179. Finally, {\tt rscv\_init()} uses \verb"Malloc" to reserve most of memory as a working 
  6180. buffer for the resource conversion. Notice that 4K are left free. You 
  6181. must leave at least 2K, and preferably a safety factor, or the AES will 
  6182. be unable to allocate memory for the file selector dialog, and your 
  6183. application will hang when calling \verb"fsel_input". By the way, an open 
  6184. virtual workstation uses about 8K, so you should do your \verb"Mallocs" after 
  6185. the workstation call.
  6186.  
  6187. We now turn our attention to {\tt do\_mode()}, which handles the main dialog of 
  6188. the converter. After getting the root address of the dialog tree, the 
  6189. states of global variables \verb"conv_def" and \verb"new_dfn" are used to set up the 
  6190. radio button array for symbol file conversion. \verb"Native_in" is used to set 
  6191. up the conversion type radio buttons. The last initialization step is to 
  6192. use the {\tt set\_text()} utility to link the file extent strings into the 
  6193. appropriate editable objects. Notice that this version of {\tt set\_text()} 
  6194. allows the string length to be explicitly supplied. For an editable text 
  6195. field object (\verb"G_FTEXT" or \verb"G_FBOXTEXT"), the length must be one greater 
  6196. than the number of blanks in the editing template.
  6197.  
  6198. Since there are \verb"TOUCHEXIT" objects in the dialog, we cannot use the 
  6199. standard {\tt hndl\_dial()} routine. Instead, the form setup and draw calls are 
  6200. coded inline. The actual \verb"form_do" call is placed inside a loop. If the 
  6201. object returned is not one of the TOUCHEXIT objects, the loop is 
  6202. terminated.
  6203.  
  6204. The two objects \verb"DEFYES" and \verb"DFNYES", which select the old and new symbol 
  6205. file formats, respectively, have been made \verb"TOUCHEXIT". If either is 
  6206. clicked, the radio button processing is done by the AES, but then 
  6207. control is returned from \verb"form_do". {\tt Do\_mode()} then tests the current input 
  6208. symbol file extent. If it is \verb"DEF" and we are switching from old to new 
  6209. mode, the extent is changed to \verb"DFN". When switching from new to old 
  6210. mode, the reverse check is made. In either case, the {\tt disp\_obj()} utility 
  6211. is used to force an immediate redraw before returning to \verb"form_do" for 
  6212. further user input.
  6213.  
  6214. When the loop terminates, {\tt do\_mode()} cleans up the screen with \verb"form_dial", 
  6215. and uses the {\tt selected()} utility to retrieve the status of the radio 
  6216. button arrays and update the global variables. Finally, {\tt map\_tree()} is 
  6217. used to apply the deselection utility to all objects in the tree, 
  6218. leaving it clean for the next invocation of {\tt do\_mode()}.
  6219.  
  6220.  
  6221. \subsection{The Belly of the Beast}
  6222.  
  6223. The routine {\tt dconv()} contains the code for actually converting the 
  6224. resource. About half of {\tt do\_conv()} is devoted to accessing disk files, 
  6225. and correctly handling error conditions which might arise. The error 
  6226. recovery could perhaps be handled more concisely with artifices like 
  6227. \verb"setjmp", but I have left it in-line for the sake of clarity.
  6228.  
  6229. {\tt Do\_conv()} also uses a collection of routines whose names begin with 
  6230. \verb"swap_" {\tt Swap\_bytes()} and {\tt swap\_words()} are the workhorse routines. They 
  6231. simply run through a given area of memory, reversing every pair of bytes 
  6232. or words, respectively. (Remember that the word swapper will only work 
  6233. on even byte boundaries, or a bus fault will occur.) The other swap 
  6234. routines do the fix up for one type of resource structure each. I'll 
  6235. take apart a couple in detail, so that you can see the similarities in 
  6236. the others.
  6237.  
  6238. Now let's follow the {\tt do\_conv()} code. The first item of business is to 
  6239. use the {\tt get\_file()} utility, followed by {\tt open\_file()}, to find and open 
  6240. the input resource file. Again, refer to a previous chapter for a discussion 
  6241. of these routines, which will handle DOS errors if they occur.
  6242.  
  6243. The Boolean \verb"conv_def" is \verb"TRUE" if we need to open a symbols file. If 
  6244. everything goes right, just substituting a new extent name (from 
  6245. variable \verb"old_def"), and doing the file open will get the file. If things 
  6246. foul up, {\tt do\_conv()} has to recover gracefully. So, it puts up the three 
  6247. button alert \verb"NODEF". The third button is an abort option; if it's picked 
  6248. we punt, closing the one open file and returning to the main dialog. 
  6249. Button one allows a continuation without the definition file (\verb"conv_def" 
  6250. is forced \verb"FALSE" so the user won't make the same mistake twice). Button 
  6251. two says try again, so {\tt get\_file()} is called to pick another file, and 
  6252. the whole process repeats.
  6253.  
  6254. Once the input file(s) are open, the operation will run to completion, 
  6255. assuming no disk errors. The mouse form is switched to an hour glass, 
  6256. and a progress indicator box is initialized on the screen.
  6257.  
  6258. The first action is to bring in the resource header only. If the 
  6259. resource is not native, that is, is not in 68000 format, its bytes must 
  6260. be swapped before using any of the counts and offsets. Note: if you've 
  6261. never dissected a resource before, this would be a good time take a look 
  6262. at the header format given in {\tt gemdefs.h} in the Developer's Kit, and 
  6263. the resource structure definitions in {\tt obdefs.h}.
  6264.  
  6265. After the swap, if necessary, the resource size field can be used. 
  6266. Before reading the rest of the resource, the size must be compared 
  6267. against the size of the buffer allocated during initialization. If there 
  6268. isn't enough room, the \verb"NOMEM" alert is displayed and control returns to 
  6269. the main dialog. (Since the biggest resource is 64K, and the Converter 
  6270. is rather small, this shouldn't ever happen. But, some people load up 
  6271. lots of desk accessories, so best to be prepared.)
  6272.  
  6273. After completing the resource input, an (admittedly kludgy) patch is 
  6274. made for the odd-byte-images problem. If the image offset pointer is 
  6275. odd, there will be problems on the ST. The fix made here relies on two 
  6276. facts. First, all images are an even number of bytes in size. Second, 
  6277. the old version of RCS DOES do an even byte synchronization AFTER 
  6278. writing the images. Therefore, if the images start on an odd byte, they 
  6279. will end on an even byte, and have one unused odd-addressed byte 
  6280. immediately following. The fixup strategy is to move all of the images 
  6281. up one byte, patch the offset in the header accordingly, and leave the 
  6282. \verb"img_odd" flag set so that the bit image swap routine will also increment 
  6283. pointers in the \verb"BITBLK" and \verb"ICONBLK"s which use the images.
  6284.  
  6285. If the resource being converted is native, we can do the image fixup 
  6286. immediately. If not, all of the other swaps have to take first, because 
  6287. the long pointers in the \verb"BITBLK"s and \verb"ICONBLK"s are in the wrong order. 
  6288. (We don't have to swap string data; it's always stored in ascending 
  6289. order.)
  6290.  
  6291. {\tt Do\_conv()} calls subroutines to swap the tree index, objects, \verb"TEDINFO"s, 
  6292. \verb"ICONBLK"s, \verb"BITBLK"s, and free string and images, in that order. We'll look 
  6293. at their actual code later. When this is finished, one of two cleanup 
  6294. actions is needed. If the resource WAS native, everything is now swapped 
  6295. except the header, which is finally reversed. If it used to be foreign 
  6296. (Intel), the pointers are now in proper 68000 order, so {\tt swap\_images()} 
  6297. can be called successfully.
  6298.  
  6299. Now it's time to write the converted resource, taking care that no error 
  6300. results. If no symbol file conversion is needed, {\tt do\_conv()} is done. The 
  6301. files are closed, the progress indicator completed, and control returns 
  6302. to {\tt rscv\_run()}, which will set the cursor back to the arrow. Otherwise, 
  6303. it's time to handle the symbols file.
  6304.  
  6305. The first two bytes in the definition file are always the symbol count. 
  6306. They are read into \verb"nsym", and a scratch copy is made in reply, and 
  6307. swapped. Just which version is written to the output file depends on 
  6308. whether it is a \verb"DFN" or \verb"DEF" file. The new (\verb"DFN")
  6309. format keeps a similar 
  6310. word order on both the ST and PC. For these files, the following code 
  6311. amounts to a verbatim copy.
  6312.  
  6313. Nsym is now used as the control variable of a loop which reads, 
  6314. converts, and writes one symbol entry on each iteration. In the old 
  6315. (\verb"DEF") file format, there was an extra word in the value field of each 
  6316. symbol's entry on the ST. Going from PC to ST, two padding zero bytes 
  6317. are added. Going the other way, they are read and discarded. For the old 
  6318. format, both the significant word of this field, as well as the 
  6319. following word field (the type) are swapped. The ten symbol bytes are 
  6320. passed through verbatim in both new and old format.
  6321.  
  6322. After swapping (old format) or simply copying (new format) of the symbol 
  6323. file is completed, file and progress box cleanup is done, and control 
  6324. returns.
  6325.  
  6326.  
  6327. \subsection{The ol' switcheroo}
  6328.  
  6329. As promised, let's now go and look at a sampling of the structure swap 
  6330. routines: one of the simplest (tree index), one of medium complexity 
  6331. (objects), and the worst of the bunch (bit images).
  6332.  
  6333. {\tt Swap\_trees()} is responsible for fixing the tree index. Its location is 
  6334. found by adding an offset from the header (\verb"rsh_trindex") to the base 
  6335. address of the resource, stored in head. (Notice that head was defined 
  6336. as a byte pointer when the buffer was allocated, so I need to type 
  6337. coerce it to a resource header pointer before making structure 
  6338. references.) The number of trees is stored in the \verb"rsh_ntree" header 
  6339. field. Each index entry is a long pointer of 32-bits, so the total size 
  6340. of the index may be found by multiplication. Finally, the swapping is 
  6341. done, first bytes within words, then words within the long pointers. 
  6342. (The order doesn't matter - work it out!)
  6343.  
  6344. {\tt Swap\_objs()} takes care of swapping fields inside of object structures. 
  6345. It begins similarly to {\tt swap\_trees()}, computing the base address of the 
  6346. objects from \verb"rsh_object", and taking the count from \verb"rsh_nobs". Since all 
  6347. of the objects are contiguous in a resource produced by RCS, and all 
  6348. fields of an object are words or longs, a byte swap is performed on the 
  6349. entire block at once. Now there are a couple of tricks. Notice that 
  6350. \verb"where" in this routine is typed as an object pointer. As the number of 
  6351. objects is counted down in the loop, \verb"where" is incremented. Because of 
  6352. its type, its actual pointer value will increase by \verb"sizeof(OBJECT)" at 
  6353. each iteration. Inside the loop, only one long field, the \verb"ob_spec", needs 
  6354. to be word swapped. When the loop completes, all object structures are 
  6355. fixed.
  6356.  
  6357. {\tt Swap\_fstr()} and {\tt swap\_fimg()} use code similar to {\tt swap\_trees()}. The other 
  6358. resource structures, \verb"TEDINFO"s, \verb"ICONBLK"s, and \verb"BITBLK"s, are transformed by 
  6359. code similar to {\tt swap\_objs()}. There is one subtlety here. These 
  6360. structures would normally be reaching by following an object's \verb"ob_spec" 
  6361. pointer. To finesse a "swap now or later" ordering problem with the 
  6362. objects, I have instead used the resource header to find the structure 
  6363. arrays. You SHOULD NOT use this technique at run time, for two reasons. 
  6364. First, if you do any object patching on the fly, the correspondence 
  6365. between objects and reference strucutres will be destroyed. Second, 
  6366. there is no way to name a non-object structure with the RCS, and 
  6367. therefore no way to reliably retrieve it with \verb"rsrc_gaddr" at execution 
  6368. time.
  6369.  
  6370. Last but not least, {\tt swap\_images()} not only takes care of switching bit 
  6371. image words, but also fixes image pointers as necessary if an odd byte 
  6372. problem has been detected. For these reasons, {\tt swap\_images} DOES follow 
  6373. pointers from the \verb"ICONBLK"s and \verb"BITBLK"s. The loop structure of the two 
  6374. sections of code will be familiar from {\tt swap\_ibs()} and {\tt swap\_bbs()}. Size 
  6375. fields within the structure are used to determine the length of each 
  6376. image. If the \verb"img_odd" flag has been set, the data pointer must be 
  6377. incremented BEFORE doing the swap, since the underlying data has already 
  6378. been moved.
  6379.  
  6380. \newpage
  6381.  
  6382. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6383. \begin{appendix}
  6384.  
  6385. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6386. \section{Commonly asked Questions}
  6387.  
  6388. Q: {\bf The ST RCS does not seem to support multiple screen resolutions 
  6389. properly. The spacing between boxes and text is not right. Is this a 
  6390. buggy RCS?}
  6391.  
  6392. A: Yes, there is a known bug in the RCS with color systems. It is 
  6393. (incorrectly) trying to use the character size for monochrome mode, 
  6394. which has twice as many vertical pixels. Digital Research is working on 
  6395. a fixed version, but for now you must either use a a monochrome system 
  6396. with RCS, or do some patches by hand.
  6397.  
  6398.  
  6399. Q: {\bf I have created a menu bar using the RCS, and now I need to display it 
  6400. using C. How do I go about it?}
  6401.  
  6402. A: First, you must find the address of the menu tree using:
  6403.  
  6404. \begin{verbatim}
  6405.     rsrc_gaddr(R_TREE, MYMENU, &ad_menu);
  6406. \end{verbatim}
  6407.  
  6408. This assumes that MYMENU is the name you gave your menu in the RCS, and 
  6409. that \verb"ad_menu" is a LONG variable. Then you make the call:
  6410.  
  6411. \begin{verbatim}
  6412.     menu_bar(ad_menu, TRUE);
  6413. \end{verbatim}
  6414.  
  6415. which will cause GEM to draw the menu and begin sending menu messages to 
  6416. your application. When your program is done, remove the menu bar with:
  6417.  
  6418. \begin{verbatim}
  6419.     menu_bar(0x0L, FALSE);
  6420. \end{verbatim}
  6421.  
  6422. before terminating. 
  6423.  
  6424.  
  6425. Q: {\bf What is the WM\_NEWTOP message? How is it different from WM\_TOPPED?}
  6426.  
  6427. A: WM\_NEWTOP is a message which is sent to an application when one of 
  6428. its windows is about to be REMOVED from the top position. Most programs 
  6429. may safely ignore this message. It is meant for use by "Paint-like" 
  6430. programs which use a window as an active buffer area and must be able to 
  6431. save away its contents before they are overlaid by a desk accessory or 
  6432. another window. WM\_NEWTOP contrasts with WM\_TOPPED, which is sent when 
  6433. the window is about to be PLACED in the top position.
  6434.  
  6435.  
  6436. Q: {\bf In RCS, what is the format of the {\tt .ICN} files which can
  6437.  be used with the LOAD option for icons and bit images?}
  6438.  
  6439. A: The RCS expects the {\tt .ICN} files to be in an obscure ASCII hexadecimal 
  6440. format which is produced by the GEM IconEditor. Unfortunately, the 
  6441. IconEditor has not yet been ported to the ST. So that you can get an 
  6442. idea of this format, I have included the images of two {\tt .ICN} files within 
  6443. the listings. You might try to extract the text and load them  into RCS 
  6444. as the data and mask for an icon. If you do it right, you should see a 
  6445. clock face.
  6446.  
  6447. If you want to build your own {\tt .ICN} files, you must keep the rigid four 
  6448. number per line format while adding and removing data lines. You may 
  6449. change the vertical and horizontal pixel counts, but the  horizontal 
  6450. count must always be a multiple of sixteen. Finally, the RCS expects the 
  6451. images to be in device-independent, monochrome format.
  6452.  
  6453.  
  6454. Q: {\bf The AES manual states "when the application is first loaded into 
  6455. memory, it should make a DOS call to modify the application's memory 
  6456. allocation". How is this done?}
  6457.  
  6458. A: When a GEM application is first loaded by the AES, all of memory is 
  6459. allocated to it. It must then release that portion which is  past the 
  6460. end of its field length. This is necessary since the AES file selector 
  6461. and the VDI open workstation and load fonts calls allocate memory, and 
  6462. the application itself may need to do its own memory management.
  6463.  
  6464. Fortunately, the standard routine APSTART will release memory for you if 
  6465. it is included as the first item in your link. It uses a setblock call 
  6466. to TOS, after determining the proper length of your application. To do 
  6467. so (quoting from APSTART), all "segment" lengths in  the base page are 
  6468. totaled and 0x100 is added for the base page length.
  6469.  
  6470.  
  6471. Q: {\bf Is it possible to patch GEM so that you must first click on the menu 
  6472. bar to active a drop-down, rather than just touching it with the cursor?  
  6473. I find it mildly irritating to open a drop-down menu accidently when I 
  6474. am merely moving the cursor around.}
  6475.  
  6476. A: As you may have guessed from the preceding discussion, the GEM menu 
  6477. algorithm is embedded deeply in the AES code and is not patchable. The 
  6478. "drop-down" architecture was chosen over "pull-downs" because it proved 
  6479. easier for novices. Unfortunately, it does cause problems for 
  6480. experienced users who mouse around the screen much faster.
  6481.  
  6482. One way to  partially avoid the problem is to design applications which 
  6483. have some  separation space between the menu bar and selectable objects. 
  6484. On the Desktop, you can move file windows away from the bar and then 
  6485. save the new layout.
  6486.  
  6487.  
  6488. Q: {\bf How can I support multiple resolutions if I need to include icons and 
  6489. images in my resource?  Do I need to have an entire separate resource 
  6490. for each resolution, or is there a simpler way?}
  6491.  
  6492. A: It is certainly possible to have an alternate resource for each 
  6493. screen mode, but it introduces problems in keeping their structure and 
  6494. naming identical. Instead, you might consider building separate files 
  6495. containing only the bit image data for your resource, with one version 
  6496. for each resolution. You might do this by copying the image definitions 
  6497. from the {\tt .C} file emitted by the RCS.
  6498.  
  6499. After you have loaded the resource, allocate some memory and  read in 
  6500. the appropriate image file. You will then have to link in the  image 
  6501. data by modifying the pointers in your resource's BITBLK and  ICONBLK 
  6502. structures. You will need to determine in advance which objects  must be 
  6503. modified, and in what order their data occurs in the image file.
  6504.  
  6505.  
  6506. Q: {\bf Why are there separate startup procedures for applications and desk 
  6507. accessories ({\tt APSTART.S} and {\tt ACCSTART.S})?}
  6508.  
  6509. A: A desk accessory is started up automatically when GEM is booted, and 
  6510. becomes more or less part of the system. An application is only run at 
  6511. the user's request, after the system has finished loading. Since they 
  6512. start at different times, they have a different "environment" to contend 
  6513. with. For instance, the application startup code has to release memory 
  6514. following the program, while the accessory has this done for it by GEM.
  6515.  
  6516.  
  6517. Q: {\bf Can a desk accessory use a resource?}
  6518.  
  6519. A: In general, no. This is because the accessories are loaded at system 
  6520. initialization time. If one later makes a {\tt rsrc\_load()} call for its 
  6521. resource, the system would allocate the resource's buffer in the user 
  6522. area of memory. This would result in a memory allocation error when the 
  6523. next application attempted to run.
  6524.  
  6525. However, it is still possible to use AES object trees within an 
  6526. accessory. You should use the RCS to create the trees, then use the C 
  6527. output option to create an image of them. This image may be included and 
  6528. compiled in the accessory's source code. At run time, you will have to 
  6529. adjust the size of the objects using {\tt rsrc\_obfix()}, as well as fix up the 
  6530. inter-structure pointers. You can use the source code of {\tt STCREATE.C} and 
  6531. the discussion of resource structure in a prior column as guides.
  6532.  
  6533.  
  6534. Q: {\bf Are there problems with the {\tt--f} (floating point)
  6535.      option in Alcyon C?}
  6536.  
  6537. A: Yes, there are a number of bugs in the Alcyon floating point library. 
  6538. In many cases, the precision of operations is poor. The only solution is 
  6539. to switch to Megamax or Lattice C to develop your floating point 
  6540. application.
  6541.  
  6542.  
  6543. Q: {\bf I've noticed that the HEAD, TAIL, and NEXT pointers in an object tree 
  6544. are actually numbers relative to the base of the tree. Does this mean 
  6545. that an object must be pre-allocated within the tree if I plan to 
  6546. {\tt objc\_add()} it later? Can an application do true dynamic allocation of 
  6547. objects without setting aside space in the tree?}
  6548.  
  6549. A: Yes, you must preallocate objects if you want to add them without 
  6550. moving the tree from the resource. The alternative is to create a 
  6551. working area from your program and copy the tree to be altered to this 
  6552. buffer. Then you can allocate new objects following those which exist, 
  6553. and link them in. The new objects must be created on 24-byte boundaries 
  6554. starting at the root of the tree. You do NOT need to copy over 
  6555. structures such as TEDINFOs, unless you plan to modify them also.
  6556.  
  6557.  
  6558. Q: {\bf I'm using the Atari Developer's Kit, and LINK68 seems to crash when 
  6559. my programs get large. Is this a bug?}
  6560.  
  6561. A: Yes, there is a known bug in using Alcyon C and LINK68 when a 
  6562. program's code area approaches 64K. It appears that jump tables 
  6563. generated by SWITCH and GOTO statements are not being properly 
  6564. relocated. Often the difficulty can be avoided by putting such modules 
  6565. at the start of the link. Otherwise, you will need to to recode SWITCH 
  6566. statements as IFs, and eliminate the GOTOs (a good practice anyway).
  6567.  
  6568. %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6569.  
  6570. \section{Listings of example source files}
  6571.  
  6572. Your disk should contain the following example source files:
  6573.  
  6574. \begin{verbatim}
  6575. \
  6576.   GEMCL02.C
  6577.   GEMCL03.C
  6578.   GEMCL04.C
  6579.   GEMCL05.C
  6580.   GEMCL06.C
  6581.   GEMCL07.C
  6582.   GEMCL09.C
  6583.   GEMCL10.C
  6584.   GEMCL11.C
  6585.   GEMCL13.C
  6586.   GEMCL15.C
  6587. GEMCL16\
  6588.   GMCL16.C
  6589.   GMCL16.H
  6590.   GMCL16.RSC
  6591.   GMCL16.RSH
  6592.   GMCL16.DFN
  6593.  
  6594. GEMCL17\
  6595.    RSCVFILE.C
  6596.    RSCVLIB.C
  6597.    RSCVMAIN.C
  6598.    RSCONV.H
  6599.    RSCVLINK.SH
  6600.    RSCONV.PRG
  6601.    RSCONV.RSC
  6602.    RSCONV.DFN
  6603.  
  6604. \end{verbatim}
  6605.  
  6606. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6607.  
  6608. % \newpage
  6609. % \include{app_a}
  6610. % \include{app_b}
  6611. % \include{app_c}
  6612.  
  6613. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6614. \end{appendix}
  6615.  
  6616. % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6617. \end{document}
  6618.